public interface APIServers { @GET Observable<String> getAPIServers(@Url String url); //Call<String> uploadFile(@PartMap Map<String, RequestBody> params); @POST("file/upload?source=android&appVersion=101") Call<String> upload(@Body RequestBody Body); }在这里,一定要切记当我们的请求体中出现@Body时,我们的开头注解里一个不能出现@Multipart或者@FormUrlEncoded
详细解释看博客:点击打开链接,里面有大神详解。
到这里,我们的接口拼接已经不存在问题了,下面就是activity中的逻辑了,我这里就只截取一些重点吧:
这里借用的网络接口还是我们仿京东里面的上传头像的接口:
上传头像
接口地址:https://www.zhaoapi.cn/file/upload
名称 | 类型 | 必填 | 说明 |
uid | string | 是 | 用户id |
file | File | 是 | 文件 |
公共参数:token=、source=android、appVersion=101
String uid="3470"; private void postFile(File file) { Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://www.zhaoapi.cn/") .addConverterFactory(ScalarsConverterFactory.create()) .build(); APIServers apiServers = retrofit.create(APIServers.class); //addFormDataPart()第一个参数为表单名字,这是和后台约定好的 MultipartBody.Builder builder = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("uid", uid); //注意,file是后台约定的参数,如果是多图,file[],如果是单张图片,file就行 builder.addFormDataPart("file", file.getName(),
RequestBody.create(MediaType.parse("image/png"),file)); RequestBody requestBody = builder.build(); Call<String> call = apiServers.upload(requestBody); call.enqueue(new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { Log.i("jiba","这是成功的===="+response.body().toString()); getContent();//上传成功后,需要重新访问接口,用来展示新的数据 } @Override public void onFailure(Call<String> call, Throwable t) { t.printStackTrace(); Log.i("jiba","这是失败===="); } }); }上传头像的重要代码就在这里了,以上是单文件+请求表单的上传,想要了解学习多文件+表单上传的可以看博客:点击打开链接
另外多说一点,我在做这个小demo中,出现了一个非常尴尬的bug,就是我在文件上传的时候,报了一个解析错误,原因还是应为retrofit的太过强大,因为它自带json传的解析功能,而为当时也没有在意这个细节,也就是没有注意到我的接口拼接中返回的数据类型是String,我就习惯性的加了这么一行代码:
然后程序就报了这么一个错误:
java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2 path $
详细解释见这里:点击打开链接 总之它的解释就是说我们json传解析错误,然后让我一顿好找啊,但也还好吧,功夫不负有心人,还是让我找到了,把.addConverterFactory()方法删了就行了!
这个问题是不是很尴尬?!!