Travailler une requête POST multipart avec Volley à l'aide de la dernière API
Dans le développement Android, l'envoi de requêtes multipart, telles que le téléchargement de fichiers et de données texte, est une tâche commune. Bien que HttpEntity ne soit plus disponible dans les versions d'API les plus récentes, il existe toujours des moyens de réaliser des requêtes multiparts à l'aide de Volley.
Création d'une requête multipart de base
Pour créer une requête multipart de base , nous pouvons étendre la classe Volley's Request comme ceci :
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.Map; class MultipartRequest extends Request<NetworkResponse> { // Listener for request response private final Response.Listener<NetworkResponse> mListener; // Listener for request error private final Response.ErrorListener mErrorListener; // Request headers private final Map<String, String> mHeaders; // Multipart mime type (e.g., "multipart/form-data; boundary=XXX") private final String mMimeType; // Request body as multipart private final byte[] mMultipartBody; // Constructor public MultipartRequest(String url, Map<String, String> headers, String mimeType, byte[] multipartBody, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) { super(Method.POST, url, errorListener); this.mListener = listener; this.mErrorListener = errorListener; this.mHeaders = headers; this.mMimeType = mimeType; this.mMultipartBody = multipartBody; } // Getters and setters // Override getHeaders() if you need to add custom headers @Override public Map<String, String> getHeaders() throws AuthFailureError { return (mHeaders != null) ? mHeaders : super.getHeaders(); } // Override getBodyContentType() to set the correct mime type for the multipart request @Override public String getBodyContentType() { return mMimeType; } // Override getBody() to return the multipart body @Override public byte[] getBody() throws AuthFailureError { return mMultipartBody; } // Override parseNetworkResponse() to parse the response as a NetworkResponse @Override protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) { try { return Response.success( response, HttpHeaderParser.parseCacheHeaders(response)); } catch (Exception e) { return Response.error(new ParseError(e)); } } // Delivering response and error @Override protected void deliverResponse(NetworkResponse response) { mListener.onResponse(response); } @Override public void deliverError(VolleyError error) { mErrorListener.onErrorResponse(error); } }
Construire le Multipart Corps
Pour construire le corps en plusieurs parties, nous pouvons utiliser les étapes suivantes :
byte[] multipartBody = new byte[0]; ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); try { // Text data buildTextPart(dos, "name", "John Doe"); buildTextPart(dos, "email", "john.doe@email.com"); // Image data Bitmap imageBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.my_image); buildImagePart(dos, "image", imageBitmap); } catch (IOException e) { e.printStackTrace(); } multipartBody = bos.toByteArray();
Inclure le corps en plusieurs parties dans la requête
Une fois le corps en plusieurs parties construit, nous pouvons l'inclure dans notre instance MultipartRequest comme donc :
MultipartRequest request = new MultipartRequest( "my_url", null, // Headers "multipart/form-data", multipartBody, new Response.Listener<NetworkResponse>() { @Override public void onResponse(NetworkResponse response) { // Handle response } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { // Handle error } });
Ajout de données texte à la demande
En plus des données d'image, vous pouvez également inclure des données texte dans votre demande :
private void buildTextPart(DataOutputStream dataOutputStream, String name, String value) throws IOException { dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd); dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + name + "\"" + lineEnd); dataOutputStream.writeBytes(lineEnd); dataOutputStream.writeBytes(value); dataOutputStream.writeBytes(lineEnd); }
Remplacez twoHyphens, border et lineEnd par les valeurs appropriées de votre code.
Code complet Exemple
L'exemple de code suivant montre une implémentation modulaire complète d'une classe VolleyMultipartRequest :
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.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; public class VolleyMultipartRequest extends Request<NetworkResponse> { private final Response.Listener<NetworkResponse> mListener; private final Response.ErrorListener mErrorListener; private final Map<String, String> mHeaders; private final String mMimeType; private final byte[] mMultipartBody; public VolleyMultipartRequest(int method, String url, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) { super(method, url, errorListener); this.mListener = listener; this.mErrorListener = errorListener; this.mHeaders = null; this.mMimeType = null; this.mMultipartBody = null; } public VolleyMultipartRequest(String url, Map<String, String> headers, String mimeType, byte[] multipartBody, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) { super(Method.POST, url, errorListener); this.mListener = listener; this.mErrorListener = errorListener; this.mHeaders = headers; this.mMimeType = mimeType; this.mMultipartBody = multipartBody; } @Override public Map<String, String> getHeaders() throws AuthFailureError { return (mHeaders != null) ? mHeaders : super.getHeaders(); } @Override public String getBodyContentType() { return mMimeType; } @Override public byte[] getBody() throws AuthFailureError { return mMultipartBody; } @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); } public static Map<String, DataPart> createMultipartRequestParts(Map<String, String> params, Map<String, DataPart> data) { Map<String, DataPart> multipartParams = new HashMap<>(); for (Map.Entry<String, String> entry : params.entrySet()) { multipartParams.put(entry.getKey(), new DataPart(entry.getValue())); } for (Map.Entry<String, DataPart> entry : data.entrySet()) { multipartParams.put(entry.getKey(), entry.getValue()); } return multipartParams; } public static byte[] createMultipartBody(Map<String, DataPart> data, String boundary) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); for (Map.Entry<String, DataPart> entry : data.entrySet()) { buildTextPart(dos, entry.getKey(), entry.getValue().getContentType(), entry.getValue().getFileName(), entry.getValue().getData()); }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!