欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Retrofit2.0 實(shí)現(xiàn)圖文(參數(shù)+圖片)上傳方法總結(jié)

 更新時(shí)間:2017年08月03日 09:57:42   作者:墨源  
本篇文章主要介紹了Retrofit2.0 實(shí)現(xiàn)圖文(參數(shù)+圖片)上傳方法總結(jié),具有一定的參考價(jià)值,有興趣的可以了解一下

最近項(xiàng)目里用到了類似圖文上傳的功能,以前都是封裝OkHttp的文件上傳功能,這次想換個(gè)姿勢(shì),想用Retrofit2.0實(shí)現(xiàn)這樣的功能,本來以為挺簡(jiǎn)單的,沒想到進(jìn)入了深坑,連續(xù)調(diào)整了好幾種姿勢(shì)都報(bào)了同一個(gè)錯(cuò),接著網(wǎng)上類似的文章找了一大推,講得都是模棱兩可,或者對(duì)多參數(shù)格式不夠友好,最后還是去看了相關(guān)的源碼,自己把這個(gè)問題提出來解決了,在這里記錄一下。

一、定義網(wǎng)絡(luò)請(qǐng)求接口

public interface GoodsReturnApiService {
  @Multipart
  @POST(Compares.GOODS_RETURN_POST)  //這里是自己post文件的地址
  Observable<GoodsReturnPostEntity> postGoodsReturnPostEntitys(@PartMap Map<String, RequestBody> map, @Part List<MultipartBody.Part> parts);
}

上面定義了一個(gè)接口用于上傳文件請(qǐng)求,有幾個(gè)注解需要說明一下, @Multipart這是Retrofit專門用于文件上傳的注解,需要配合@POST一起使用。

方法postGoodsReturnPostEntitys(@PartMap Map<String, RequestBody> map, @Part List<MultipartBody.Part> parts)第一個(gè)參數(shù)使用注解@PartMap用于多參數(shù)的情況,如果是單個(gè)參數(shù)也可使用注解@Part。

在類型Map<String, RequestBody>中,Map第一個(gè)泛型String是服務(wù)器接收用于文件上傳參數(shù)字段的Key,第二個(gè)泛型RequestBody是OkHttp3包裝的上傳參數(shù)字段的Value,這也是圖文上傳成功的關(guān)鍵所在。在后面會(huì)具體說到。

第二個(gè)參數(shù)使用注解@Part用于文件上傳,多文件上傳使用集合類型List<MultipartBody.Part>,單文件可以使用類型MultipartBody.Part,具體的使用同樣后面講。

這里著重說明一下,postGoodsReturnPostEntitys(@PartMap Map<String, RequestBody> map, @Part List<MultipartBody.Part> parts)方法參數(shù)這樣寫純屬個(gè)人習(xí)慣,你也可以直接使用一個(gè)參數(shù)postGoodsReturnPostEntitys(@PartMap Map<String, RequestBody> map),不過后面對(duì)RequestBody的處理方式也要跟著變化,這里就不詳細(xì)說了,只會(huì)介紹上面這種簡(jiǎn)便清晰的方式。

二、初始化Retrofit

public class HttpRequestClient {

  public static final String TAG = "HttpRequestClientTAG";

  private static Retrofit retrofit;

  private static OkHttpClient getOkHttpClient() {
    //日志顯示級(jí)別
    HttpLoggingInterceptor.Level level= HttpLoggingInterceptor.Level.BODY;
    //新建log攔截器
    HttpLoggingInterceptor loggingInterceptor=new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
      @Override
      public void log(String message) {
        Log.d(TAG, message);
      }
    });
    loggingInterceptor.setLevel(level);
    //定制OkHttp
    OkHttpClient.Builder httpClientBuilder = new OkHttpClient
        .Builder();
    //OkHttp進(jìn)行添加攔截器loggingInterceptor
    httpClientBuilder.addInterceptor(loggingInterceptor);
    return httpClientBuilder.build();
  }

  public static Retrofit getRetrofitHttpClient(){
    if(null == retrofit){
      synchronized (HttpRequestClient.class){
        if(null == retrofit){
          retrofit = new Retrofit.Builder()
              .client(getOkHttpClient())
              .baseUrl(Compares.URL)
              .addConverterFactory(GsonConverterFactory.create())
              .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
              .build();
        }
      }
    }
    return retrofit;
  }
}

為了演示,Retrofit封裝比較簡(jiǎn)陋,為的是查看網(wǎng)絡(luò)攔截,就不詳細(xì)說了。

三、發(fā)起文件上傳請(qǐng)求

private void postGoodsPicToServer(){
    Map<String,RequestBody> params = new HashMap<>();
    //以下參數(shù)是偽代碼,參數(shù)需要換成自己服務(wù)器支持的
    params.put("type", convertToRequestBody("type"));
    params.put("title",convertToRequestBody("title"));
    params.put("info",convertToRequestBody("info");
    params.put("count",convertToRequestBody("count"));

    //為了構(gòu)建數(shù)據(jù),同樣是偽代碼
    String path1 = Environment.getExternalStorageDirectory() + File.separator + "test1.jpg";
    String path2 = Environment.getExternalStorageDirectory() + File.separator + "test1.jpg";

    List<File> fileList = new ArrayList<>();

    fileList.add(new File(path1));
    fileList.add(new File(path2));

    List<MultipartBody.Part> partList = filesToMultipartBodyParts(fileList);

    HttpRequestClient.getRetrofitHttpClient().create(GoodsReturnApiService.class)
        .postGoodsReturnPostEntitys(params,partList)
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Observer<GoodsReturnPostEntity>() {
          @Override
          public void onSubscribe(@NonNull Disposable d) {

          }

          @Override
          public void onNext(@NonNull GoodsReturnPostEntity goodsReturnPostEntity) {

          }

          @Override
          public void onError(@NonNull Throwable e) {

          }

          @Override
          public void onComplete() {

          }
        });
}

上面的params和fileList都是構(gòu)造的偽代碼,需要根據(jù)自己項(xiàng)目的業(yè)務(wù)需求改變。

下面是上傳文件成功第一個(gè)關(guān)鍵,對(duì)參數(shù)請(qǐng)求頭(姑且叫這個(gè)名字,對(duì)應(yīng)Retrofit上傳文件時(shí)參數(shù)那部分請(qǐng)求頭,下文件(圖片)請(qǐng)求頭同理,對(duì)應(yīng)文件那部分請(qǐng)求頭)的content-type賦值,使用convertToRequestBody()方法。

private RequestBody convertToRequestBody(String param){
    RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), param);
    return requestBody;
  }

因?yàn)镚sonConverterFactory.create()轉(zhuǎn)換器的緣故,會(huì)將參數(shù)請(qǐng)求頭的content-type值默認(rèn)賦值application/json,如果沒有進(jìn)行這步轉(zhuǎn)換操作,就可以在OKHttp3的日志攔截器中查看到這樣的賦值,這樣導(dǎo)致服務(wù)器不能正確識(shí)別參數(shù),導(dǎo)致上傳失敗,所以這里需要對(duì)參數(shù)請(qǐng)求頭的content-type設(shè)置一個(gè)正確的值:text/plain。

下面是上傳文件成功第二個(gè)關(guān)鍵的地方,將文件(圖片)請(qǐng)求頭的content-type使用方法filesToMultipartBodyParts()對(duì)其賦值"image/png",并返回MultipartBody.Part集合。

private List<MultipartBody.Part> filesToMultipartBodyParts(List<File> files) {
    List<MultipartBody.Part> parts = new ArrayList<>(files.size());
    for (File file : files) {
      RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file);
      MultipartBody.Part part = MultipartBody.Part.createFormData("multipartFiles", file.getName(), requestBody);
      parts.add(part);
    }
    return parts;
  }

說到底,還是對(duì)參數(shù)請(qǐng)求頭和文件(圖片)請(qǐng)求頭的content-type屬性賦值處理,不要讓Retrofit 默認(rèn)賦值,這里才是關(guān)鍵。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android實(shí)戰(zhàn)教程第四十三篇之上拉加載與下拉刷新

    Android實(shí)戰(zhàn)教程第四十三篇之上拉加載與下拉刷新

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)戰(zhàn)教程第四十三篇之上拉加載與下拉刷新,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Android設(shè)置當(dāng)TextView中的文字超過TextView的容量時(shí)用省略號(hào)代替

    Android設(shè)置當(dāng)TextView中的文字超過TextView的容量時(shí)用省略號(hào)代替

    這篇文章主要介紹了Android設(shè)置當(dāng)TextView中的文字超過TextView的容量時(shí)用省略號(hào)代替 ,需要的朋友可以參考下
    2017-03-03
  • Android TextView漸變顏色和方向及動(dòng)畫效果的設(shè)置詳解

    Android TextView漸變顏色和方向及動(dòng)畫效果的設(shè)置詳解

    TextView的在安卓中可以理解為一個(gè)文本視圖控件,Android的視圖控件的基類是View類,可以理解的TextView是View的子類。我們通常在.XML布局文件中會(huì)為文本視圖控件指定各種屬性來設(shè)置它的樣式,今天我們要講的當(dāng)然不是傳統(tǒng)常見的那種,將會(huì)帶有漸變顏色和方向及動(dòng)畫效果
    2021-11-11
  • 分享五種Android常用布局方式

    分享五種Android常用布局方式

    Android布局是應(yīng)用界面開發(fā)的重要一環(huán),在Android中,共有五種布局方式,分別是:FrameLayout(框架布 局),LinearLayout (線性布局),AbsoluteLayout(絕對(duì)布局),RelativeLayout(相對(duì)布局),TableLayout(表格布局),小編通過本文逐一給大家詳解
    2015-11-11
  • Android性能優(yōu)化之弱網(wǎng)優(yōu)化詳解

    Android性能優(yōu)化之弱網(wǎng)優(yōu)化詳解

    這篇文章主要為大家介紹了Android性能優(yōu)化之弱網(wǎng)優(yōu)化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Android自定義LinearLayout布局顯示不完整的解決方法

    Android自定義LinearLayout布局顯示不完整的解決方法

    這篇文章主要給大家介紹了關(guān)于Android自定義LinearLayout但布局顯示不完整的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • Android仿360懸浮小球自定義view實(shí)現(xiàn)示例

    Android仿360懸浮小球自定義view實(shí)現(xiàn)示例

    本篇文章主要介紹了Android仿360懸浮小球自定義view實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • Android創(chuàng)建Menu菜單實(shí)例

    Android創(chuàng)建Menu菜單實(shí)例

    這篇文章主要介紹了Android創(chuàng)建Menu菜單實(shí)例,講述了Android菜單項(xiàng)的創(chuàng)建方法,在Android應(yīng)用程序開發(fā)中非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2014-10-10
  • Android?NDK開發(fā)(C語言--聯(lián)合體與枚舉)

    Android?NDK開發(fā)(C語言--聯(lián)合體與枚舉)

    這篇文章主要介紹了Android?NDK開發(fā)C語言聯(lián)合體與枚舉,共用體是一種特殊的數(shù)據(jù)類型,允許您在相同的內(nèi)存位置存儲(chǔ)不同的數(shù)據(jù)類型。您可以定義一個(gè)帶有多成員的共用體,但是任何時(shí)候只能有一個(gè)成員帶有值。下面詳細(xì)介紹該內(nèi)容,需要的朋友可以參考一下
    2021-12-12
  • Android編程獲取APP應(yīng)用程序基本信息輔助類【APP名稱、包名、圖標(biāo),版本號(hào)等】

    Android編程獲取APP應(yīng)用程序基本信息輔助類【APP名稱、包名、圖標(biāo),版本號(hào)等】

    這篇文章主要介紹了Android編程獲取APP應(yīng)用程序基本信息輔助類,可實(shí)現(xiàn)針對(duì)APP名稱、包名、圖標(biāo),版本號(hào)等信息的獲取功能,需要的朋友可以參考下
    2017-12-12

最新評(píng)論