1. 程式人生 > >Retrofit實現檔案上傳和下載【二】

Retrofit實現檔案上傳和下載【二】

概述

通過前一篇的部落格介紹,我們已經對Retrofit的使用有了一個大概的瞭解,今天來講講利用Retrofit進行檔案的上傳和下載

檔案上傳

伺服器使用的是SSH框架,因此這裡是以struts2的方式來獲取資料的,我這裡定義了三個欄位用來接收上傳過來的資料

private File file;//獲取單個檔案
private File[] files;//獲取多個檔案
private String description;

單檔案上傳

先定義咱們的介面

@Multipart
@POST("user!getFile")
//description表示key
Call<RequestBody> upFile(@Part
("description") RequestBody description, @Part MultipartBody.Part file);

解釋:@Multipart表示請求傳送multipart資料,需要配合@Part一起使用,MultipartBody.Part用來封裝需要上傳的檔案,RequestBody用來封裝一段文字

下面來看看具體實現

 //把file封裝到RequestBody中
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), files[0]);
//再把RequestBody封裝到MultipartBody.Part中,第一個引數file就是和伺服器約定的key
MultipartBody.Part body = MultipartBody.Part.createFormData("file", files[0].getName(), requestFile); String descriptionString = "hello, 這是檔案描述"; RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), descriptionString); Call<RequestBody> call = fileService.upFile(description, body);

多檔案上傳

在介紹多檔案上傳前,先對RequestBody、MultipartBody、MultipartBody.Builder、MultipartBody.Part這幾個類作一個簡單說明,方便我們對下面的程式碼有一個清晰的認識

1.RequestBody是MultipartBody的父類
2.MultipartBody.Part通過createXXX方法來建立請求用的資料
3.MultipartBody.Part可以傳入RequestBody物件來建立請求用的資料
4.MultipartBody.Builder可以新增多個MultipartBody.Part
5.通過MultipartBody.Builder的build()方法返回MultipartBody物件
6.RequestBody的create(MediaType contentType, File file)方法,把File封裝到請求體中
詳細內容可以去看看okhttp的API

多檔案的上傳大致有三種形式:
1.第一種方法(太Low不可取)

@Multipart
@POST("user!getFiles")
Call<RequestBody> upFile(@Part("description") RequestBody description, @Part MultipartBody.Part file1,@Part MultipartBody.Part file2,@Part MultipartBody.Part file3);

這種實現方式和單檔案差不多,這裡就不再贅述了
2.第二種方法

@Multipart
@POST("user!getFiles")
Call<RequestBody> upFiles(@Part("files") MultipartBody files);
@Multipart
@POST("user!getFiles")
Call<RequestBody> upFiles(@Part("files") RequestBody files);

解釋:這兩種形式其實就是一種啦,下面介紹MultipartBody的實現方式,files對應伺服器裡的key

MultipartBody.Builder builder = new MultipartBody.Builder();
for(int i = 0; i < files.length; ++i){
    RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), files[i]);
    builder.addFormDataPart("file", files[i].getName(), requestFile);
}
Call<RequestBody> call = fileService.upFiles(builder.build());

解釋:這裡的file不是伺服器的key
3.第三種方法

@Multipart
@POST("user!getFiles")
Call<RequestBody> upFiles(@PartMap Map<String,RequestBody> files);

Map裡的String裡存了key,但不僅僅有Key,還包括了別的

Map<String, RequestBody> map = new HashMap<>();
for (int i = 0; i < files.length; ++i) {
    RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), files[i]);
    //files 對應伺服器那邊的key,具體寫法就是下面這種形式
    map.put("files\"; filename=\"" + files[i].getName(), requestFile);
}
Call<RequestBody> call = fileService.upFiles(map);

檔案下載

@GET("user!downloadFile")
//需要注意這裡傳入的是ResponseBody而不是之前的RequestBody
Call<ResponseBody> downloadFile();

具體實現和普通請求差不多,最後通過response.body().byteStream()獲取到InputStream以後,通過流的方式把檔案寫到本地,需要注意的是當檔案過大的時候,需要在下載檔案的方法上新增@Streaming註解