privatevoidupLoadOnClick(View v) {? ? ? ? String upUrl ="/mnt/sdcard/pic/test.jpg";//指定要上傳的文件finalProgressDialog dia =newProgressDialog(this);? ? ? ? dia.setMessage("加載中....");? ? ? ? dia.show();? ? ? ? RequestParams params =newRequestParams(upUrl);? ? ? ? params.addBodyParameter("file",newFile(upUrl));? ? ? ? x.http().post(params,newCallback.CommonCallback() {@OverridepublicvoidonSuccess(String result) {//加載成功回調(diào)烁落,返回獲取到的數(shù)據(jù)Log.i(TAG,"onSuccess: "+ result);? ? ? ? ? ? }@OverridepublicvoidonFinished() {? ? ? ? ? ? ? ? dia.dismiss();//加載完成}@OverridepublicvoidonCancelled(CancelledException cex) {? ? ? ? ? ? }@OverridepublicvoidonError(Throwable ex,booleanisOnCallback) {? ? ? ? ? ? }? ? ? ? });? ? }
我在項目中通過以上方法進行圖片上傳,發(fā)現(xiàn)有點小問題,或許是我把這個方法使 用不到位剔猿。
在與服務(wù)器聯(lián)調(diào)時,同事總是告訴我沒有收到文件流數(shù)據(jù)俭正,結(jié)果肯定是上傳失敗谷扣。后來繼續(xù)看代碼跟進,發(fā)現(xiàn)通過
` params.addBodyParameter("file", new File(upUrl));`
這種方式傳遞文件數(shù)據(jù)芹彬,默認的請求數(shù)據(jù)類型并不是文件類型所需要的multipart/form-data類型數(shù)據(jù)蓄髓。
通過看相應(yīng)源碼,我們在使用xUtils實現(xiàn)網(wǎng)絡(luò)請求時舒帮,通過
`RequestParams params = new RequestParams(Constants.ADD_ZONE_PLANE);`創(chuàng)建請求会喝,然后通過
` params.setRequestBody(body);`傳遞請求參數(shù)陡叠。
其實setRequestBody(RequestBody requestBody)方法是調(diào)用RequestParams的父類BaseParams中的方法:
publicvoidsetRequestBody(RequestBody requestBody) {this.requestBody = requestBody;? ? }
考慮是參數(shù)數(shù)據(jù)類型問題,我們就從傳遞參數(shù)RequestBody入手好乐,發(fā)現(xiàn)在xUtils中匾竿,默認有:
FileBody,InputStreamBody,MultipartBody及StringBody等幾種類型的請求Body,當然這些都是RequestBody的子類 蔚万。
發(fā)現(xiàn)MultipartBody類型中岭妖,有這個方法:
privatevoidgenerateContentType() {? ? ? ? String boundaryPostfix = Double.toHexString(Math.random() *0xFFFF);? ? ? ? boundaryPostfixBytes = boundaryPostfix.getBytes();? ? ? ? contentType ="multipart/form-data; boundary="+newString(BOUNDARY_PREFIX_BYTES) + boundaryPostfix;? ? }
看到返回的類型是multipart/form-data...,正是我想要的反璃,所以請求參數(shù)就從MultipartBody入手考慮上傳文件昵慌。
MultipartBody類的構(gòu)造方法如下:
//參數(shù)分別是要傳入的數(shù)據(jù),和數(shù)據(jù)編碼類型 public MultipartBody(List multipartParams, String charset) {if(!TextUtils.isEmpty(charset)) {? ? ? ? ? ? this.charset = charset;? ? ? ? }? ? ? ? this.multipartParams = multipartParams;? ? ? ? generateContentType();...}
從構(gòu)造方法需要的參數(shù)開始淮蜈,我們一步一步地實現(xiàn)MultipartBody所需要的數(shù)據(jù)斋攀。
//創(chuàng)建List對象Listlist=newArrayList<>();//給list中添加數(shù)據(jù),filePah是上傳的文件路徑梧田,比如sd卡中圖片list.add(newKeyValue("file",newFile(filePah)));//文件流數(shù)據(jù)//其它參數(shù)淳蔼,根據(jù)項目而定,比如我的項目中要傳入的參數(shù)是json格式的list.add(newKeyValue("parameters", json.toString()));//創(chuàng)建MultipartBodyMultipartBody body=newMultipartBody(list,"UTF-8");//添加請求參數(shù)params.setRequestBody(body);
這樣就可以實現(xiàn)文件上傳裁眯,最后貼下整個請求方法的相關(guān)代碼:
//要傳遞給服務(wù)器的json格式參數(shù)JSONObject json =newJSONObject();try{? ? ? ? ? ? json.put("devId", id);? ? ? ? ? ? json.put("devName", devName);? ? ? ? ? ? json.put("keyWord", keyWord);? ? ? ? }catch(JSONException e) {? ? ? ? ? ? e.printStackTrace();? ? ? ? }//構(gòu)建RequestParams對象鹉梨,傳入請求的服務(wù)器地址URLRequestParams params =newRequestParams(Constants.UPLOAD_FILE);? ? ? ? params.setAsJsonContent(true);? ? ? ? List list =newArrayList<>();? ? ? ? list.add(newKeyValue("file",newFile(filePah)));? ? ? ? list.add(newKeyValue("parameters", json.toString()));? ? ? ? MultipartBody body =newMultipartBody(list,"UTF-8");? ? ? ? params.setRequestBody(body);? ? ? ? x.http().post(params,neworg.xutils.common.Callback.CommonCallback() {@OverridepublicvoidonSuccess(String result) {? ? ? ? ? ? ? ? LogUtil.e("請求結(jié)果:"+ result);? ? ? ? ? ? }@OverridepublicvoidonFinished() {//上傳完成}@OverridepublicvoidonCancelled(CancelledException cex) {//取消上傳}@OverridepublicvoidonError(Throwable ex,booleanisOnCallback) {//上傳失敗LogUtil.e("請求失敗:"+ ex.toString());? ? ? ? ? ? }? ? ? ? });