recently participated in the CSDN blog star, I hope you give a vote, thank you ~ Point hereCast me a vote.Preface
In the development, we often need to implement file upload, more common is the image upload, such as modify the size of something like. But this feature does not have a default implementation class in Android and iOS, For Android We can use the Httpclient.jar provided by Apache to implement this function, which depends on the class of multipartentity in Apache's Httpmime.jar. I just want to implement a file upload function, but I also have to download a jar package, and this jar package dozens of KB, this is not as if the human! Today we come to implement the file upload function, and understand their principles.
In the previous article HTTP POST request message format Analysis and Java implementation File Upload we introduced the HTTP POST message format, if there is no knowledge of the post message format students can read this article first.
Custom Implementation Multipartentity
We know that the use of network protocols to transmit data is simply to follow a protocol, and we are basically using the HTTP protocol when developing mobile applications. The HTTP protocol is a set of TCP-based network request protocol, you transfer data according to the format specified in the protocol, and then the server returned to you data. If your protocol parameter is passed incorrectly, then the server can only give you a return error.
This is a bit similar to the spy on the signal, they have a rule of the code, the two sides meet, a said: The king cover the Tiger, b pair: Pagoda Town River Demon. Yes, say something, not right, kill this B. HTTP is also the case, adding headers and parameters to the HTTP request, and the server parsing according to the parameters. Shaped like:
post/api/feed/http/1.1 here is header data--delimiter parameter--delimiter parameter 2
Just send the request to the server according to the format! Let's look at the implementation of Multipartentity:
public class Multipartentity implements httpentity {private final static char[] Multipart_chars = "-_1234567890ABCDEFG Hijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz ". ToCharArray (); /** * NewLine character */private final String new_line_str = "\ r \ n"; Private final String Content_Type = "Content-type:"; Private final String content_disposition = "content-disposition:"; /** * Text parameter and Character set */private final String Type_text_charset = "text/plain; Charset=utf-8 "; /** * Byte Throttle parameter */private final String Type_octet_stream = "Application/octet-stream"; /** * Binary Parameters */private final byte[] binary_encoding = "content-transfer-encoding:binary\r\n\r\n". GetBytes (); /** * Text parameter */private final byte[] bit_encoding = "content-transfer-encoding:8bit\r\n\r\n". GetBytes (); /** * Delimiter * */private String mboundary = null; /** * Output stream */bytearrayoutputstream Moutputstream = new Bytearrayoutputstream (); Public Multipartentity () {this.mboundary = Generateboundary (); }/** * Generate delimiter * * @return */private final String generateboundary () {Final StringBuffer bu f = new StringBuffer (); Final random rand = new Random (); for (int i = 0; i < i++) {Buf.append (Multipart_chars[rand.nextint (multipart_chars.length))); } return buf.tostring (); }/** * The delimiter at the beginning of the parameter * * @throws IOException */private void Writefirstboundary () throws IOException { Moutputstream.write ("--" + Mboundary + "\ r \ n"). GetBytes ()); }/** * Add text parameter * * @param key * @param value */public void Addstringpart (final String Paramnam E, final String value) {Writetooutputstream (paramname, Value.getbytes (), Type_text_charset, Bit_encoding, ""); /** * Writes data to the output stream * * @param key * @param rawdata * @param type * @param encodingbytes * @param fileName */ private void Writetooutputstream (String paramname, byte[] rawdata, String type, byte[] encodingbytes, String fileName) {try {writefirstboundary (); Moutputstream.write ((content_type + TYPE + new_line_str). GetBytes ()); Moutputstream. Write (Getcontentdispositionbytes (paramname, fileName)); Moutputstream.write (encodingbytes); Moutputstream.write (RawData); Moutputstream.write (New_line_str.getbytes ()); } catch (Final IOException e) {e.printstacktrace (); }}/** * Add binary parameters, such as Bitmap's byte stream parameter * * @param key * @param rawdata */public void Addbinarypa RT (String paramname, final byte[] rawdata) {writetooutputstream (paramname, RawData, Type_octet_stream, Binary_enco DING, "No-file"); }/** * Add file parameter, can implement file upload function * * @param key * @param file */public void Addfilepart (final String Key, Final File fiLe) {InputStream fin = null; try {fin = new FileInputStream (file); Writefirstboundary (); Final String type = content_type + Type_octet_stream + new_line_str; Moutputstream.write (Getcontentdispositionbytes (Key, File.getname ())); Moutputstream.write (Type.getbytes ()); Moutputstream.write (binary_encoding); Final byte[] tmp = new byte[4096]; int len = 0; while (len = Fin.read (tmp))! =-1) {moutputstream.write (tmp, 0, Len); } moutputstream.flush (); } catch (Final IOException e) {e.printstacktrace (); } finally {closesilently (FIN); }} private void closesilently (closeable closeable) {try {if (closeable! = null) { Closeable.close (); }} catch (Final IOException e) {e.printstacktrace (); }} private byte[] GetcontentdiSpositionbytes (String paramname, String fileName) {StringBuilder StringBuilder = new StringBuilder (); Stringbuilder.append (content_disposition + "form-data; Name=\ "" + paramname + "\" "); The text parameter does not have the filename parameter and is set to NULL if (! Textutils.isempty (fileName) {stringbuilder.append ("; Filename=\ "" + fileName + "\" "); } return Stringbuilder.append (NEW_LINE_STR). toString (). GetBytes (); } @Override public Long getcontentlength () {return Moutputstream.tobytearray (). length; } @Override Public Header getContentType () {return new Basicheader ("Content-type", "multipart/form-data; boundary= "+ mboundary); } @Override public Boolean ischunked () {return false; } @Override public Boolean isrepeatable () {return false; } @Override public Boolean isstreaming () {return false; } @Override public void WriteTo (final outputstream outstream) throws Ioexception {///parameter at the very end of Terminator final String endstring = "--" + mboundary + "--\r\n"; Write Terminator Moutputstream.write (Endstring.getbytes ()); Outstream.write (Moutputstream.tobytearray ()); } @Override Public Header getcontentencoding () {return null; } @Override public void Consumecontent () throws IOException, unsupportedoperationexception {if (i Sstreaming ()) {throw new unsupportedoperationexception ("streaming entity does not implemen T #consumeContent () "); }} @Override public InputStream getcontent () {return new Bytearrayinputstream (Moutputstream.tobytearray ( )); }}
Users can passAddstringpart, Addbinarypart, addfilepart to add parameters, respectively, to add string parameters, add binary parameters, add file parameters. In Multipartentity, there is a Bytearrayoutputstream object that writes these parameters to the output stream, which executes when the network request is executed .
method writes the byte stream data of all parameters to the output stream of a TCP connection established with the server, thus passing our parameters to the server. Before this, of course, we need to write the data in the format to the Bytearrayoutputstream object.
For example, I want to send a text to the server, a bitmap picture, a file, that is, the request has three parameters. The code is as follows:
Multipartentity multipartentity = new multipartentity (); Text parameter multipartentity.addstringpart ("type", "my text parameter"); Bitmap bmp = Bitmapfactory.decoderesource (Getresources (), r.drawable.thumb); Binary parameter multipartentity.addbinarypart ("Images", Bitmaptobytes (BMP)); File parameter multipartentity.addfilepart ("Images", New file ("Storage/emulated/0/test.jpg")); Post Request HttpPost post = new HttpPost ("url"); Set the multipartentity to post post.setentity (multipartentity); Use the HTTP client to execute the request HttpClient HttpClient = new Defaulthttpclient (); Httpclient.execute (POST);
The output format of the multipartentity is formatted as follows:
Post/api/feed/http/1.1content-type:multipart/form-data; boundary=o3fhj53z-oktoduaelfbanu4pzhp4-user-agent:dalvik/1.6.0 (Linux; U Android 4.4.4; M040 build/ktu84p) host:www.myhost.comconnection:keep-aliveaccept-encoding:gzipcontent-length:168518-- O3fhj53z-oktoduaelfbanu4pzhp4-content-type:text/plain; Charset=utf-8content-disposition:form-data; Name= "type" Content-transfer-encoding:8bitthis my type--o3fhj53z-oktoduaelfbanu4pzhp4-content-type:application/ Octet-streamcontent-disposition:form-data; Name= "Images"; Filename= "No-file" content-transfer-encoding:binary here is the binary data--o3fhj53z-oktoduaelfbanu4pzhp4-content-type of bitmap: Application/octet-streamcontent-disposition:form-data; Name= "File"; Filename= "Storage/emulated/0/test.jpg" content-transfer-encoding: Binary here is the binary data of the picture file--O3FHJ53Z-OKTODUAELFBANU4PZHP4---
See familiar, this is the post message format we mentioned at the beginning of the article. That's right! Httpentity is the message format that is responsible for constructing the parameters into HTTP, what format the text parameter is, what format the file is in, and what type, and these formats are fixed. Once constructed, the output stream of the HTTP request is passed through the WriteTo (outputstream) function when the request is executed, and then all of these parameter data is output to the HTTP output stream.
Understand the truth, and look at the code should understand it.
implement file upload in volleyVolley is Google's official Web request library, which is very streamlined and excellent, but they also do not have the support to add File upload functionality by default. Today we are going to define a request to implement the file upload function, or need to use the Multipartentity class above, see the code below:
/** * Multipartrequest, the returned result is in String format * @author mrsimple */public class Multipartrequest extends Request<string> { Multipartentity mmultipartentity = new multipartentity (); Public Multipartrequest (HttpMethod method, String URL, map<string, string> params, requestlistener<str Ing> listener) {Super (method, URL, params, listener); }/** * @return * */Public multipartentity getmultipartentity () {return mmultipartentity; } @Override Public String Getbodycontenttype () {return Mmultipartentity.getcontenttype (). GetValue (); } @Override Public byte[] GetBody () {bytearrayoutputstream bos = new Bytearrayoutputstream (); try {//writes parameters in Mmultipartentity to Bos mmultipartentity.writeto (BOS); } catch (IOException e) {log.e ("", "IOException writing to Bytearrayoutputstream"); } return Bos.tobytearray (); } @Override protected VoiD deliverresponse (String response) {mlistener.onresponse (response); } @Override protected response<string> parsenetworkresponse (Networkresponse Response) {String parsed; try {parsed = new String (Response.data, Httpheaderparser.parsecharset (response.headers)); } catch (Unsupportedencodingexception e) {parsed = new String (response.data); } return Response.success (parsed, httpheaderparser.parsecacheheaders (Response)); }}
Use the sample code:
Multipartrequest multipartrequest = new Multipartrequest (httpmethod.post, "/HTTP server address", NULL, new Requestlistener<string> () {@Override public void Onst Art () {//TODO auto-generated method stub} @Override public void OnComplete (int stcode, string response, String errmsg) {}}); Gets the Multipartentity object multipartentity multipartentity = Multipartrequest.getmultipartentity (); Multipartentity.addstringpart ("Content", "Hello"); Bitmap Bitmap = Bitmapfactory.decoderesource (Getresources (), r.drawable.thumb); Bitmap parameter Multipartentity.addbinarypart ("Images", bitmaptobytes (bitmap)); File parameter Multipartentity.addfilepart ("Images", New file ("Storage/emulated/0/test.jpg")); Build request queue Requestqueue queue = RequestqueUe.newrequestqueue (Context); Add the request to the queue queue.addrequest (multipartrequest);
This is my post to my app:
Custom Multipartentity in Android for uploading files and uploading files using the volley library