使用 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("upload/")
Call<ResponseBody> register(
@Query("name") String cardName,
@Query("phone") String callphone,
@Query("address") String address,
@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);
上傳文件到服務端示例
如果你已經有你的後端項目, 您可以依靠下面的示例代碼。我們使用一個簡單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設備上報文件到您的後端服務器的第一個 步驟。
上傳出現類型錯誤解決方案:
其中一定要添加上filename這個
public interface CheckIn { @Multipart @POST("/check/checkin.action") Call<ResponseCode> checkIn(@Part("image\"; filename=\"文件名.jpg") RequestBody file); }創建RequestBody對象作爲參數上傳
RequestBody imgFile = RequestBody.create(MediaType.parse("image/*"), imgFile);
以上方法解決了文件正常上傳的問題,但是文件名卻只能是常量,固定死了,並不是理想的結果,那麼接下來就是解決這個問題。
首先是不需要在interface上定義文件名,而是通過Map來上傳所有參數。
參數定義如下:
try { Staff staff = (Staff) SharedPreferencesUtils.getObject(context,LoginActivity.LOGIN_USER); RequestBody staffPhone = RequestBody.create(MediaType.parse("text/plain"), staff.getPhone()); RequestBody time = RequestBody.create(MediaType.parse("text/plain"), "時間"); RequestBody address = RequestBody.create(MediaType.parse("text/plain"), "地點"); RequestBody type = RequestBody.create(MediaType.parse("text/plain"), "類型"); Map<String, RequestBody> map = new HashMap<>(); map.put("staffPhone",staffPhone); map.put("checkTime",time); map.put("checkAddress",address); map.put("checkType",type); if (imgFile != null) { RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), imgFile); map.put("image\"; filename=\""+imgFile.getName()+"", fileBody); } HttpService.checkIn(map); } catch (IOException e) { e.printStackTrace(); }interface如下:
public interface CheckIn{ @Multipart @POST("/check/checkin.action") Call<ResponseCode> checkIn(@PartMap Map<String, RequestBody> params); }
OK,搞定。
原文鏈接:http://www.jianshu.com/p/acfefb0a204f
著作權歸作者所有,轉載請聯繫作者獲得授權,並標註“簡書作者”。