Use Volley to upload files and volley to upload files
Upload files in a browser, and then analyze the packets through Wireshark. It is found that the data sent is like this.
MIME Multipart Media Encapsulation, Type: multipart/form-data, Boundary: "----WebKitFormBoundary1UBMMKIkN58civN4" [Type: multipart/form-data] First boundary: ------WebKitFormBoundary1UBMMKIkN58civN4\r\n Encapsulated multipart part: Content-Disposition: form-data; name="name"\r\n\r\n Data (16 bytes) Boundary: \r\n------WebKitFormBoundary1UBMMKIkN58civN4\r\n Encapsulated multipart part: (image/png) Content-Disposition: form-data; name="photo[]"; filename="Screenshot (2).png"\r\n Content-Type: image/png\r\n\r\n Portable Network Graphics Boundary: \r\n------WebKitFormBoundary1UBMMKIkN58civN4\r\n Encapsulated multipart part: (image/png) Boundary: \r\n------WebKitFormBoundary1UBMMKIkN58civN4\r\n Encapsulated multipart part: (image/png) Boundary: \r\n------WebKitFormBoundary1UBMMKIkN58civN4\r\n Encapsulated multipart part: (image/png) Boundary: \r\n------WebKitFormBoundary1UBMMKIkN58civN4\r\n Encapsulated multipart part: (image/png) Last boundary: \r\n------WebKitFormBoundary1UBMMKIkN58civN4--\r\n
First, define an HttpEntity,
package cc.dewdrop.volleydemo.utils;import com.android.volley.VolleyLog;import org.apache.http.Header;import org.apache.http.HttpEntity;import org.apache.http.message.BasicHeader;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.Closeable;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import javax.activation.MimetypesFileTypeMap;/** * Created by Tingkuo on 12/1/2015. */public class FileUploadEntity implements HttpEntity { private static final String TAG = FileUploadEntity.class.getSimpleName(); private static final String BOUNDARY = "__FILE_UPLOAD_ENTITY__"; private ByteArrayOutputStream mOutputStream; public FileUploadEntity() { mOutputStream = new ByteArrayOutputStream(); try { writeFirstBoundary(); } catch (IOException e) { e.printStackTrace(); } } private void writeFirstBoundary() throws IOException { VolleyLog.e("writeFirstBoundary"); mOutputStream.write(("--" + BOUNDARY + "\r\n").getBytes()); mOutputStream.write(("Content-Disposition: form-data; name=\"" + "name" + "\"\r\n\r\n").getBytes()); mOutputStream.write("Content-Transfer-Encoding: binary\n\n".getBytes()); mOutputStream.flush(); } private void writeLastBoundary() throws IOException { VolleyLog.e("writeLastBoundary"); mOutputStream.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes()); } public void addFile(final String key, final File file) { VolleyLog.e("addFile"); InputStream inputStream = null; try { mOutputStream.write(("\r\n--" + BOUNDARY + "\r\n").getBytes()); StringBuilder stringBuilderContentDisposition = new StringBuilder(); stringBuilderContentDisposition.append("Content-Disposition: "); stringBuilderContentDisposition.append("form-data; "); stringBuilderContentDisposition.append("name=\"" + key + "\"; "); stringBuilderContentDisposition.append("filename=\"" + file.getName() + "\"\r\n"); mOutputStream.write(stringBuilderContentDisposition.toString().getBytes()); StringBuilder stringBuilderContentType = new StringBuilder(); stringBuilderContentType.append("Content-Type: "); stringBuilderContentType.append(new MimetypesFileTypeMap().getContentType(file).toString()); stringBuilderContentType.append("\r\n\r\n"); mOutputStream.write(stringBuilderContentType.toString().getBytes()); inputStream = new FileInputStream(file); final byte[] buffer = new byte[1024]; int len = 0; while ((len = inputStream.read(buffer)) != -1) { VolleyLog.e("len --> %s", String.valueOf(len)); mOutputStream.write(buffer, 0, len); } VolleyLog.e("===last====len --> %s", String.valueOf(len)); mOutputStream.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { closeSilently(inputStream); } } private void closeSilently(Closeable closeable) { try { if (closeable != null) { closeable.close(); } } catch (final IOException e) { e.printStackTrace(); } } @Override public boolean isRepeatable() { return false; } @Override public boolean isChunked() { return false; } @Override public long getContentLength() { return mOutputStream.toByteArray().length; } @Override public Header getContentType() { return new BasicHeader("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); } @Override public Header getContentEncoding() { return null; } @Override public InputStream getContent() throws IOException, UnsupportedOperationException { return new ByteArrayInputStream(mOutputStream.toByteArray()); } @Override public void writeTo(OutputStream outputStream) throws IOException { writeLastBoundary(); outputStream.write(mOutputStream.toByteArray()); } @Override public boolean isStreaming() { return false; } @Override public void consumeContent() throws IOException { }}
Here, we will explain that Multifile upload is supported. The data format consists of four parts: Content-Type, First boundary, binary data [], and Last boundary. You can insert multiple files using addFile. The Boundary delimiter must be used between files. Each file requires Content-Disposition and Content-Type.
Then, customize a Request and use different constructor methods as needed.
package cc.dewdrop.volleydemo.utils;import com.android.volley.AuthFailureError;import com.android.volley.NetworkResponse;import com.android.volley.Request;import com.android.volley.Response;import com.android.volley.Response.Listener;import com.android.volley.Response.ErrorListener;import com.android.volley.toolbox.HttpHeaderParser;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.util.HashMap;import java.util.Map;/** * Created by Tingkuo on 12/2/2015. */public class FileUploadRequest extends Request<String> { private final Listener<String> mListener; private FileUploadEntity mFileUploadEntity = new FileUploadEntity(); private Map<String, String> mHeaders = new HashMap<>(); public FileUploadRequest(String url, Listener<String> listener) { this(url, listener, null); } public FileUploadRequest(String url, Listener<String> listener, ErrorListener errorListener) { this(Method.POST, url, listener, errorListener); } public FileUploadRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { super(method, url, errorListener); this.mListener = listener; } public FileUploadEntity getFileUploadEntity() { return mFileUploadEntity; } @Override public String getBodyContentType() { return mFileUploadEntity.getContentType().getValue(); } public void addHeader(String key, String value) { mHeaders.put(key, value); } @Override public Map<String, String> getHeaders() throws AuthFailureError { return mHeaders; } @Override public byte[] getBody() throws AuthFailureError { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { mFileUploadEntity.writeTo(outputStream); } catch (IOException e) { e.printStackTrace(); } return outputStream.toByteArray(); } @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)); } @Override protected void deliverResponse(String response) { if (mListener != null) { mListener.onResponse(response); } }}
The code is written in other types of requests in Volley.
Finally, how to call
private void simpleUploadFile() { File file = new File(Environment.getExternalStorageDirectory().getPath() + "/upload.png"); fileUploadRequest = new FileUploadRequest( Request.Method.POST, urlList.get(2), new Response.Listener<String>() { @Override public void onResponse(String response) { textViewInfo.setText("Post Succeed:\n" + response.replace("<br>", "\n")); Log.e(TAG, response); dialog.dismiss(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { textViewInfo.setText("Post Failed:\n" + error.getMessage()); Log.e(TAG, error.getMessage()); dialog.dismiss(); } } ); fileUploadRequest.addHeader("User-Agent", "Android 5.1.1"); FileUploadEntity fileUploadEntity = fileUploadRequest.getFileUploadEntity(); fileUploadEntity.addFile("file[]", file); fileUploadEntity.addFile("file[]", file); fileUploadEntity.addFile("file[]", file); fileUploadEntity.addFile("file[]", file); fileUploadEntity.addFile("file[]", file); requestQueue.add(fileUploadRequest); dialog.show(); }
Instantiate a new Request object, pass in Method and Url, get Entity through the Request object, pass in the file to be uploaded through addFile () Method, and add requestQueue, the usage is the same as that of other types of requests.
Note:
You need to add the following dependencies:
compile 'org.apache.httpcomponents:httpcore:4.4.4' compile 'org.apache.httpcomponents:httpmime:4.5.1' compile files('libs/volley.jar') compile files('libs/activation.jar')