Retrofit学习之文件和参数上传

个人主页:http://shiyiliang.cn

今天主要来学习Retrofit的文件和参数的上传,如果你不是很了解上传的原理,你可以看下文件上传原理,先了解下文件上传的基本原理。

参数上传

1. 参数个数不是很多时

@FormUrlEncoded
@POST("upload")
Call<ResponseBody> uploadParams(@Field("username")String username,@Field("token")String token);

使用直接传入参数值即可

2. 多个参数上传

@FormUrlEncoded
@POST("upload")
Call<ResponseBody> uploadParams(@FieldMap Map<String,String> map);   

调用的时候,直接传入一个map集合,即可

3. 通用的方法

@POST("upload")
Call<ResponseBody> uploadParams(@Body RequestBody body);

调用时,传入一个RequestBody对象,OkHttp库中有一个专门用来构建参数上传的RequestBody子类,即FormBody,如下

FormBody body=new FormBody.Builder()
                .add("username","admin")
                .add("token","sjdkdjows=dmzkkshf")
                .build();

在使用的时候,直接调用uploadParams (body)即可实现上传。

文件上传

1. 单个文件上传

 @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);

2. 多文件上传

使用@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);
使用@Part实现
@Multipart
@POST("upload")
Call<ResponseBody> uploadFiles(@Part List<MultipartBody.Part> parts);

调用代码如下:

RequestBody fileRQ = RequestBody.create(MediaType.parse("image/*"), file);

MultipartBody.Part part = MultipartBody.Part.createFormData("picture", file.getName(), fileRQ);

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"));
MultipartBody.Part two=MultipartBody.Part.createFormData("one","one.png",fileTwo);
List<MultipartBody.Part> parts=new ArrayList<>();
parts.add(part);
parts.add(two);

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

文件和参数混合上传

@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);

通用上传方式

接口定义,注意这个时候没有@Multipart

 @POST("upload")
 Call<ResponseBody> uploadFile(@Body RequestBody body);

利用MultipartBody来实现通用的参数和文件上传

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("multipart/form-data"), file);
        MultipartBody.Part part = MultipartBody.Part.createFormData("picture", file.getName(), fileRQ);

        RequestBody body=new MultipartBody.Builder()
                .addFormDataPart("userName","lange")
                .addFormDataPart("token","dxjdkdjkj9203kdckje0")
                .addFormDataPart("header",file.getName(),fileRQ)
                .build();
        Call<ResponseBody> uploadCall = downloadService.uploadFile(body);
        uploadCall.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                Log.i("upload", response.isSuccessful() + "");
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {

            }
        });

看下服务端的输出:

userName-->lange
token-->dxjdkdjkj9203kdckje0
/Users/lange/Desktop/web/out/artifacts/web_war_exploded/upload/1.png

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

注意:

  1. 如果在上传文件的时候,定义:
 @Multipart
@POST("upload")
Call<ResponseBody> uploadOneFile(@Part RequestBody file);

显示下面的错误:

 @Part annotation must supply a name or use MultipartBody.Part parameter type. (parameter #1)
  1. 如果@Part加上参数,并RequestBody作为参数,上传文件,服务端识别不出来这是一个文件,会当做一个参数上传的例子
 @Multipart
@POST("upload")
Call<ResponseBody> uploadOneFile(@Part("file") RequestBody file);
  1. 如果使用MultipartBody.Part作为参数,又加上了名字
uploadOneFile(@Part("file") MultipartBody.Part file)

则会显示下面的错误

@Part parameters using the MultipartBody.Part must not include a part name in the annotation

如果你觉得文章让你有一些收获,你就赞赏下或者关注一下~。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,730评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,484评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,668评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,202评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,129评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,853评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,140评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,780评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,060评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,095评论 2 315
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,908评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,663评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,181评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,307评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,582评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,141评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,381评论 2 339

推荐阅读更多精彩内容