Retrofit multpart上传文件

Retrofit multpart上传文件

在最初的http协议中,没有定义上传文件的Method,为了实现这个功能,http协议组改造了post请求,添加了一种post规范,设定这种规范的Content-Type为multipart/form-data;boundary= b o u n d , 其 中 {bound},其中 bound,{bound}是定义的分隔符,用于分割各项内容(文件,key-value对),不然服务器无法正确识别各项内容。post body里需要用到,尽量保证随机唯一。

  • 在retrofit中:

    • @retrofit2.http.Multipart: 标记一个请求是multipart/form-data类型,需要和@retrofit2.http.POST一同使用,并且方法参数必须是@retrofit2.http.Part注解。
    • @retrofit2.http.Part: 代表Multipart里的一项数据,即用${bound}分隔的内容块。
  • 在okhttp3中:

    • okhttp3.MultipartBody :multipart/form-data 的抽象封装,继承okhttp3.RequestBody
    • okhttp3.MultipartBody.Part:multipart/form-data里的一项数据。

文件上传

单个文件上传

 @Multipart
 @POST("upload")
Call<ResponseBody> uploadOneFile(@Part MultipartBody.Part body);

调用的使用MultipartBody.Part来构造一个Part对象参数

String name = etFileName.getText().toString().trim();
name = TextUtils.isEmpty(name) ? "1.png" : name;
String path = Environment.getExternalStorageDirectory() + File.separator + name;
File file = new File(path);

RequestBody fileRQ = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part part MultipartBody.Part.createFormData("picture", file.getName(), fileRQ);

Call<ResponseBody> uploadCall = downloadService.uploadOneFile(part);

多文件上传

使用@PartMap实现

@Multipart
@POST("upload")
Call<ResponseBody> uploadFiles(@PartMap Map<String, RequestBody> map);

调用方法

RequestBody fb = RequestBody.create(MediaType.parse("text/plain"), "hello,retrofit");
RequestBody fileTwo = RequestBody.create(MediaType.parse("image/*"), new File(Environment.getExternalStorageDirectory()
                + file.separator + "original.png"));
Map<String, RequestBody> map = new HashMap<>();
//这里的key必须这么写,否则服务端无法识别
map.put("file\"; filename=\""+ file.getName(), fileRQ);
map.put("file\"; filename=\""+ "2.png", fileTwo);

Call<ResponseBody> uploadCall = downloadService.uploadFiles(map);

文件和参数混合上传

接口定义,注意这个时候没有@Multipart
当我们采用这种方式上传的时候,不能再接口上加上@Multipart的注解,否者会报错

@POST("api/community/room/person/face/reg")
    Observable<JSONObject> updateFace(@Header("Authorization") String header,@Body RequestBody requestBody);

调用

File file = new File(face_url);
        RequestBody fileRQ = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        RequestBody body=new MultipartBody.Builder()
                .addFormDataPart("params1","params1")
                .addFormDataPart("params2","params2")
                .addFormDataPart("params3","params3")
                .addFormDataPart("file",file.getName(),fileRQ)
                .build();
        RetrofitConfig.createService().updateFace(RetrofitConfig.getHeaders(token),body)

或者使用@Multipart注解(此混合上传的方式未成功,建议使用上面的方式)

@Multipart
@POST("upload")
Call<ResponseBody> uploadFile(@Part("body") RequestBody body, @Part MultipartBody.Part file);

调用

MultipartBody.Part part = MultipartBody.Part.createFormData("picture", file.getName(), fileRQ);
RequestBody fb =RequestBody.create(MediaType.parse("text/plain"), "hello,retrofit");
Call<ResponseBody> uploadCall = downloadService.uploadFile(fb,part);

注意:
1.如果在上传文件的时候,定义:

 @Multipart
@POST("upload")
Call<ResponseBody> uploadOneFile(@Part RequestBody file);

显示下面的错误:

@Part annotation must supply a name or use MultipartBody.Part parameter type. (parameter #1)

2.如果@Part加上参数,并RequestBody作为参数,上传文件,服务端识别不出来这是一个文件,会当做一个参数上传的例子

@Multipart
@POST("upload")
Call<ResponseBody> uploadOneFile(@Part("file") RequestBody file);

3.如果使用MultipartBody.Part作为参数,又加上了名字

uploadOneFile(@Part("file") MultipartBody.Part file)

则会显示下面的错误

@Part parameters using the MultipartBody.Part must not include a part name in the annotation
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值