Android使用Volley框架定制PostUploadRequest上传文件
发现问题
项目中有发表动态的功能,该功能可以将文本和图片上传至服务器。
Volley通过定制PostUploadRequest实现文件上传的功能,本文以一张图片上传为例。
数据格式
以下为项目中图片上传实例的数据格式
多张图片上传可通过添加——WebKitFormBoundary内容实现
POST/CloudLife/user/socialHTTP/1.1 Host:localhost Connection:keep-alive Cache-Control:max-age=0 Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Origin:http://localhost User-Agent:Mozilla/5.0(WindowsNT6.3;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/31.0.1650.63Safari/537.36 Content-Type:multipart/form-data;boundary=----WebKitFormBoundaryzayymBT8Owg2UzBR Referer:http://localhost/CloudLife/upload.jsp Accept-Encoding:gzip,deflate,sdch Accept-Language:zh-CN,zh;q=0.8 Cookie:CLOUD_LIFE=03F21B9A9D9B4FF2BF443290A9CD8E2C;USER=18060506304;JSESSIONID=C4AB532929FA43230FA193A98197F962 Content-Length:12444 ------WebKitFormBoundaryzayymBT8Owg2UzBR Content-Disposition:form-data;name="text" 发表的圈子内容 ------WebKitFormBoundaryzayymBT8Owg2UzBR Content-Disposition:form-data;name="file";filename="这里是文件名" Content-Type:image/png 这里空一行接下来是二进制图片文件内容 ------WebKitFormBoundaryzayymBT8Owg2UzBR-- 这里为空白的一行
总共有加上结尾行,有五行,图片的二进制数,整个算一行;下面来分析下:
1、第一行:”–”+boundary+“\r\n”;
文件上传在提交数据的开始标志不变;
2、第二行:Content-Disposition:form-data;name=”参数的名称”;filename=”上传的文件名”+“\r\n”
3、第三行:Content-Type:文件的mime类型+“\r\n”
这一行是文件上传必须要的,而普通的文字提交可有可无,mime类型需要根据文档查询;
4、第四行:”\r\n”
5、第五行文件的二进制数据+“\r\n”:
结尾行:”–”+boundary+“–”+“\r\n”
可以同时上传多个文件,上传多个文件的时候重复1、2、3、4、5步,在最后的一个文件的末尾加上统一的结束行。
上传的图像实体类
importjava.io.ByteArrayOutputStream; importandroid.graphics.Bitmap; /* *上传的图像实体类 **/ publicclassFormImage{ //参数的名称 privateStringmName; //文件名 privateStringmFileName; //文件的mime,需要根据文档查询 privateStringmMime; //需要上传的图片资源,因为这里测试为了方便起见,直接把bitmap传进来,真正在项目中一般不会这般做, //而是把图片的路径传过来,在这里对图片进行二进制转换 privateBitmapmBitmap=null; publicFormImage(Bitmapbitmap){ this.mBitmap=bitmap; } publicStringgetName(){ return"file"; } publicStringgetFileName(){ return"add.png"; } //对图片进行二进制转换 publicbyte[]getValue(){ ByteArrayOutputStreambos=newByteArrayOutputStream(); mBitmap.compress(Bitmap.CompressFormat.JPEG,80,bos); returnbos.toByteArray(); } //因为我知道是png文件,所以直接根据文档查的 publicStringgetMime(){ return"image/png"; } }
定制PostUploadRequest
importjava.io.ByteArrayOutputStream; importjava.io.IOException; importjava.io.UnsupportedEncodingException; importjava.util.HashMap; importjava.util.Map; importorg.apache.http.protocol.HTTP; importorg.json.JSONException; importorg.json.JSONObject; importcom.android.volley.AuthFailureError; importcom.android.volley.DefaultRetryPolicy; importcom.android.volley.NetworkResponse; importcom.android.volley.ParseError; importcom.android.volley.Request; importcom.android.volley.Response; importcom.android.volley.toolbox.HttpHeaderParser; importandroid.util.Log; /* *发送文件的volley *post请求Cookie **/ publicclassPostUploadRequestextendsRequest{ privateMap sendHeader=newHashMap (); //正确数据的时候回掉用 privateResponse.Listener mListener; //请求数据通过参数的形式传入 privateStringcontent; privateFormImagemImage; //数据分隔线 privateStringBOUNDARY="----CloudLifeUpLoadImage"; privateStringMULTIPART_FORM_DATA="multipart/form-data"; publicPostUploadRequest(Stringurl,Stringtext,FormImageItem,Response.Listener listener,Response.ErrorListenererrorListener){ super(Method.POST,url,errorListener); this.mListener=listener; setShouldCache(false); mImage=Item; content=text; //设置请求的响应事件,因为文件上传需要较长的时间,所以在这里加大了,设为5秒 setRetryPolicy(newDefaultRetryPolicy(5000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT)); } /* *这里开始解析数据 *@paramresponse *Responsefromthenetwork *@return **/ @Override protectedResponse parseNetworkResponse(NetworkResponseresponse){ try{ //防止中文乱码 @SuppressWarnings("deprecation") StringjsonString=newString(response.data,HTTP.UTF_8); JSONObjectjsonObject=newJSONObject(jsonString); Log.w("upLoad","jsonObject"+jsonObject.toString()); returnResponse.success(jsonObject,HttpHeaderParser.parseCacheHeaders(response)); }catch(UnsupportedEncodingExceptione){ returnResponse.error(newParseError(e)); }catch(JSONExceptionje){ returnResponse.error(newParseError(je)); } } /* *回调正确的数据 *@paramresponse *Theparsedresponsereturnedby **/ @Override protectedvoiddeliverResponse(JSONObjectresponse){ mListener.onResponse(response); } @Override publicMap getHeaders()throwsAuthFailureError{ returnsendHeader; } publicvoidsetSendCookie(Stringcookie){ sendHeader.put("Cookie",cookie); } @Override publicbyte[]getBody()throwsAuthFailureError{ ByteArrayOutputStreambos=newByteArrayOutputStream(); StringBuffersb=newStringBuffer(); if(content==null){ /** *图片 */ /*第一行*/ //`"--"+BOUNDARY+"\r\n"` sb.append("--"+BOUNDARY+"\r\n"); /*第二行*/ //Content-Disposition:form-data;name="参数的名称";filename="上传的文件名"+ //"\r\n" sb.append("Content-Disposition:form-data;"); sb.append("name=\""); sb.append(mImage.getName()); sb.append("\""); sb.append(";filename=\""); sb.append(mImage.getFileName()); sb.append("\""); sb.append("\r\n"); /*第三行*/ //Content-Type:文件的mime类型+"\r\n" sb.append("Content-Type:"); sb.append(mImage.getMime()); sb.append("\r\n"); /*第四行*/ //"\r\n"空白的一行 sb.append("\r\n"); try{ bos.write(sb.toString().getBytes("utf-8")); /*第五行*/ //文件的二进制数据+"\r\n" bos.write(mImage.getValue()); bos.write("\r\n".getBytes("utf-8")); }catch(IOExceptione){ e.printStackTrace(); } /*结尾行*/ //`"--"+BOUNDARY+"--"+"\r\n"` StringendLine="--"+BOUNDARY+"--"+"\r\n"; try{ bos.write(endLine.toString().getBytes("utf-8")); }catch(IOExceptione){ e.printStackTrace(); } Log.v("upLoad","=====formImage====\n"+bos.toString()); returnbos.toByteArray(); } /** *文字 */ /*第一行*/ //`"--"+BOUNDARY+"\r\n"` sb.append("--"+BOUNDARY+"\r\n"); /*第二行*/ //Content-Disposition:form-data;name="text"+"\r\n" sb.append("Content-Disposition:form-data;"); sb.append("name=\""); sb.append("text"); sb.append("\""); sb.append("\r\n"); /*第三行*/ //"\r\n"空白的一行 sb.append("\r\n"); /*第四行*/ //文本内容 sb.append(content); sb.append("\r\n"); if(mImage==null){ /*结尾行*/ //`"--"+BOUNDARY+"--"+"\r\n"` StringendLine="--"+BOUNDARY+"--"+"\r\n"; try{ bos.write(sb.toString().getBytes("utf-8")); bos.write(endLine.toString().getBytes("utf-8")); }catch(IOExceptione){ e.printStackTrace(); } Log.v("upLoad","=====formImage====\n"+bos.toString()); returnbos.toByteArray(); }else{ /** *图片 */ /*第一行*/ //`"--"+BOUNDARY+"\r\n"` sb.append("--"+BOUNDARY+"\r\n"); /*第二行*/ //Content-Disposition:form-data;name="参数的名称";filename="上传的文件名"+ //"\r\n" sb.append("Content-Disposition:form-data;"); sb.append("name=\""); sb.append(mImage.getName()); sb.append("\""); sb.append(";filename=\""); sb.append(mImage.getFileName()); sb.append("\""); sb.append("\r\n"); /*第三行*/ //Content-Type:文件的mime类型+"\r\n" sb.append("Content-Type:"); sb.append(mImage.getMime()); sb.append("\r\n"); /*第四行*/ //"\r\n"空白的一行 sb.append("\r\n"); try{ bos.write(sb.toString().getBytes("utf-8")); /*第五行*/ //文件的二进制数据+"\r\n" bos.write(mImage.getValue()); bos.write("\r\n".getBytes("utf-8")); }catch(IOExceptione){ e.printStackTrace(); } } /*结尾行*/ //`"--"+BOUNDARY+"--"+"\r\n"` StringendLine="--"+BOUNDARY+"--"+"\r\n"; try{ bos.write(endLine.toString().getBytes("utf-8")); }catch(IOExceptione){ e.printStackTrace(); } Log.v("upLoad","=====formImage====\n"+bos.toString()); returnbos.toByteArray(); } //Content-Type:multipart/form-data;boundary=----------8888888888888 @Override publicStringgetBodyContentType(){ returnMULTIPART_FORM_DATA+";boundary="+BOUNDARY; } }
实例
RequestQueuemQueue=SingleRequestQueue.getRequestQueue(); FormImageimage; if(imageUri!=null){ Bitmapbitmap=null; try{//将路径转化成bitmap bitmap=BitmapFactory.decodeStream( getContentResolver().openInputStream(imageUri)); }catch(FileNotFoundExceptione1){ e1.printStackTrace(); } image=newFormImage(bitmap); }else image=null; PostUploadRequestpost=newPostUploadRequest(C.api.userIcon,null,image, newResponse.Listener(){ @Override publicvoidonResponse(JSONObjectjsonObject){ try{ //TODO }catch(JSONExceptione){ e.printStackTrace(); } } },newResponse.ErrorListener(){ @Override publicvoidonErrorResponse(VolleyErrorerror){ Log.e("VolleyError",error.getMessage(),error); } }); if(!customer.getCookie().equals("")){ //向服务器发起post请求时加上cookie字段 post.setSendCookie(customer.getCookie()); } mQueue.add(post);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。