Retrofit 2.0 超能實踐(三),輕鬆實現檔案/多圖片上傳/Json字串
通過前兩篇姿勢的入門
通過對Retrofit2.0的前兩篇的基礎入門和案例實踐,掌握了怎麼樣使用Retrofit訪問網路,加入自定義header,包括加入SSL證書,基本的除錯基礎,coolkie同步,但很多需求需要檔案的上傳,今天主題就來分享怎麼用Retrofit2.0 上傳檔案和圖片。
使用 Retrofit1.x上傳檔案
大家都知道在2.0以前版本上傳圖片的姿勢
public interface ApiManager { @Multipart @POST("/user/addCarInfo") void addCarInfo(@QueryMap Map<String, Object> options, @Part("file") TypedFile file, Callback<JsonElement> response); }
使用 Retrofit 2.X 上傳
Retrofit 2上傳檔案
使用2,0,我們發現TypedFile型別被私有化了 ,無法繼續使用1.9的傳方式無法再上層呼叫了,可以MultipartBody.Part代替
public interface FileUploadService { @Multipart @POST("upload") Call<ResponseBody> upload(@Part("description") RequestBody description, @Part MultipartBody.Part file); }
具體用法。
// 建立 RequestBody,用於封裝 請求RequestBody RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file); // MultipartBody.Part is used to send also the actual file name MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile); // 新增描述 String descriptionString = "hello, 這是檔案描述"; RequestBody description = RequestBody.create( MediaType.parse("multipart/form-data"), descriptionString); // 執行請求 Call<ResponseBody> call = service.upload(description, body); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { Log.v("Upload", "success"); } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { Log.e("Upload error:", t.getMessage()); } });
}
上報一張圖片
@Multipart
@POST("you methd url upload/")
Call<ResponseBody> uploadFile(
@Part("avatar\\\\"; filename=\\\\"avatar.jpg") RequestBody file);
上報多張圖片
@POST("upload/")
Call<ResponseBody> uploadFiles(@Part("filename") String description,
@Part("pic\\\\"; filename=\\\\"image1.png") RequestBody imgs1,
@Part("pic\\\\"; filename=\\\\"image2.png") RequestBody imgs2,
@Part("pic\\\\"; filename=\\\\"image3.png") RequestBody imgs3,
@Part("pic\\\\"; filename=\\\\"image4.png") RequestBody imgs4);
如果圖片數量不確定
@Multipart
@POST("{url}")
Observable<ResponseBody> uploadFiles(
@Path("url") String url,
@Part("filename") String description,
@PartMap() Map<String, RequestBody> maps);
或者:
@Multipart
@POST("{url}")
Observable<ResponseBody> uploads(
@Path("url") String url,
@Part("description") RequestBody description,
@Part("filekey") MultipartBody.Part file);
圖片和引數同時上報
@Multipart
@POST("upload/")
Call<ResponseBody> register(
@QueryMap Map<String , String> usermaps,
@Part("avatar\\\\"; filename=\\\\"avatar.jpg") RequestBody avatar,
);
此種方式讓你很好的解決使用者註冊問題。包含使用者全部資訊
上面的程式碼片段中顯示的程式碼初始化(RequestBody 和description),以及如何使用檔案上傳服務。正如已經提到的,從OkHttp RequestBody類用於描述。需要兩個RequestBody.create()方法
除了描述,必須將新增檔案包裝成MultipartBody的例項。這就是你需要使用適當的從客戶端上傳檔案。此外,您可以新增createFormData中的uploadFile(Uri fileUri)方法和重用
設定 Content-Type
請注意設定的內容型別。如果你攔截底層OkHttp客戶機和更改內容型別application / json, 你的伺服器可能反序列化過程出現的問題。請確保你沒有自定義multipart/form-data
upLoad圖片也可以具體指明Content-Type 為 “image/jpg”格式的
RequestBody requestFile =
RequestBody.create(MediaType.parse("image/jpg"), mFile);
還有常用的:
上傳Json
@POST("/uploadJson")
Observable<ResponseBody> uploadjson(
@Body RequestBody jsonBody);
upLoadJson 也可以具體指明Content-Type 為 “application/json”格式的
具體組裝我們的RequestBody則可以這樣:
RequestBody body=
RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), jsonString);
接著可以這樣呼叫:
// 執行請求
Call<ResponseBody> call = service.uploadJson(description, body);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call,
Response<ResponseBody> response) {
Log.v("Upload", "success");
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e("Upload error:", t.getMessage());
}
});
}
至於伺服器返回什麼型別的model, 開發者可以自定義 譬如你可以把APi 中的 ResponseBody 指定為你自己的javaBean
,當然上層構建Callback
的時候也必須是 Call<MyBean>
@POST("/uploadJson")
Observable<MyBean> uploadjson(
@Body RequestBody jsonBody);
上傳檔案到服務端示例
如果你已經有你的後端專案, 您可以依靠下面的示例程式碼。我們使用一個簡單api 上傳伺服器。此外我們告訴api 傳入引數的請求,因為我們使用的是Node.js
解析的回撥函式,我們記錄每個欄位來顯示其輸出。
method: 'POST',
path: '/upload',
config: {
payload: {
maxBytes: 209715200,
output: 'stream',
parse: false
},
handler: function(request, reply) {
var multiparty = require('multiparty');
var form = new multiparty.Form();
form.parse(request.payload, function(err, fields, files) {
console.log(err);
console.log(fields);
console.log(files);
return reply(util.inspect({fields: fields, files: files}));
});
}}
安卓客戶端收到返回型別的字串, 我們將接收到的上傳成功的狀態的回撥。當然你可以處理也可以不處理。
下面你將看到一個成功的請求的輸出端和有效載荷的解析。第一個空物件。之後,你可以看到欄位只描述作為請求的一部分。接著可以收到檔案描述,檔案大小,檔案暱稱和儲存路徑。
伺服器解析有效資料的日誌
Null
{ description: [ 'hello, this is description speaking' ] }
{ picture:
[ { fieldName: 'picture',
originalFilename: '20160312_095248.jpg',
path: '/var/folders/rq/q_m4_21j3lqf1lw48fqttx_80000gn/T/X_sxX6LDUMBcuUcUGDMBKc2T.jpg',
headers: [Object],
size: 39369 } ] }
回顧
檔案上傳是最新的應用程式中必不可少的功能,你可以將此功能整合在您的應用程式使用翻新。本文指導您完成你的Android裝置上報檔案到您的後端伺服器的第一個步驟。
Retrofit 2.0系列請閱讀簡書
更多技術文章請關注碼小白
Retrofit 2.0系列請閱讀
第一時間獲取技術文章請關注微信公眾號!