Volley is a popular Android library for making HTTP requests. In earlier API versions, HttpEntity was used in conjunction with Volley for multipart form data submission. However, with the deprecation of HttpEntity in API 22 and its complete removal in API 23, developers are left with a challenge.
In this article, we will demonstrate a working solution for performing multipart POST requests without the use of HttpEntity. The provided code allows you to upload multiple files along with text data.
The implementation presented here consists of two classes: MultipartActivity and MultipartRequest. MultipartActivity handles the preparation of multipart form data, while MultipartRequest extends Volley's Request class and overrides necessary methods to handle multipart body and process the server response.
To utilize this solution, follow these steps:
MultipartActivity.java:
import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.widget.Toast; import com.android.volley.NetworkResponse; import com.android.volley.Response; import com.android.volley.VolleyError; import com.example.multipartvolley.MultipartRequest; import com.example.multipartvolley.VolleySingleton; import java.util.HashMap; import java.util.Map; public class MultipartActivity extends Activity { private Context context = this; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Assuming you have prepared file data in fileData1 and fileData2 String url = "http://192.168.1.100/api/postfile"; MultipartRequest multipartRequest = new MultipartRequest(url, null, "multipart/form-data", multipartBody, new Response.Listener<NetworkResponse>() { @Override public void onResponse(NetworkResponse response) { Toast.makeText(context, "Upload successfully!", Toast.LENGTH_SHORT).show(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(context, "Upload failed!\r\n" + error.toString(), Toast.LENGTH_SHORT).show(); } }) { @Override protected Map<String, String> getParams() { Map<String, String> params = new HashMap<>(); params.put("text_field1", "Value for text field 1"); params.put("text_field2", "Value for text field 2"); return params; } @Override protected Map<String, DataPart> getByteData() { Map<String, DataPart> params = new HashMap<>(); params.put("file_name1", new DataPart("file_name1.txt", "file content 1".getBytes(), "text/plain")); params.put("file_name2", new DataPart("file_name2.png", fileData1, "image/png")); return params; } }; VolleySingleton.getInstance(context).addToRequestQueue(multipartRequest); } }
MultipartRequest.java:
import com.android.volley.AuthFailureError; import com.android.volley.NetworkResponse; import com.android.volley.ParseError; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.HttpHeaderParser; import java.util.HashMap; import java.util.Map; class MultipartRequest extends Request<NetworkResponse> { private final Response.Listener<NetworkResponse> mListener; private final Response.ErrorListener mErrorListener; private Map<String, String> mHeaders; private Map<String, DataPart> mByteData; MultipartRequest(String url, Map<String, String> headers, String contentType, Map<String, DataPart> byteData, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) { super(Method.POST, url, errorListener); this.mListener = listener; this.mErrorListener = errorListener; this.mHeaders = headers; this.mByteData = byteData; } @Override public Map<String, String> getHeaders() throws AuthFailureError { return mHeaders != null ? mHeaders : super.getHeaders(); } @Override public String getBodyContentType() { return "multipart/form-data; boundary=" + getBoundary(); } @Override public byte[] getBody() throws AuthFailureError { return encodeMultipartData(mByteData, getBoundary()); } private String getBoundary() { return Long.toHexString(System.currentTimeMillis()); } @Override protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) { try { return Response.success( response, HttpHeaderParser.parseCacheHeaders(response)); } catch (Exception e) { return Response.error(new ParseError(e)); } } @Override protected void deliverResponse(NetworkResponse response) { mListener.onResponse(response); } @Override public void deliverError(VolleyError error) { mErrorListener.onErrorResponse(error); } protected static byte[] encodeMultipartData(Map<String, DataPart> dataParts, String boundary) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); try { for (Map.Entry<String, DataPart> entry : dataParts.entrySet()) { dos.writeBytes(twoHyphens + boundary + lineEnd); dos.writeBytes("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + "; filename=\"" + entry.getValue().getFileName() + "\"" + lineEnd); dos.writeBytes(String.format("Content-Type: %s%s", entry.getValue().getType(), lineEnd)); dos.writeBytes(lineEnd); dos.write(entry.getValue().getContent()); dos.writeBytes(lineEnd); } dos.writeBytes(lineEnd); dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); return bos.toByteArray(); } catch (IOException e) { e.printStackTrace(); return null; } } class DataPart { private String fileName; private byte[] content; private String type; DataPart(String fileName, byte[] content, String type) { this.fileName = fileName; this.content = content; this.type = type; } String getFileName() { return fileName; } byte[] getContent() { return content; } String getType() { return type; } } }
This code handles multipart form data requests where you can pass both file and text parameters securely to the server. It's crucial to note that the final code is not for production use and should be modified according to your specific requirements.
The above is the detailed content of How to Make Multipart POST Requests with Volley Without Using HttpEntity?. For more information, please follow other related articles on the PHP Chinese website!