首頁 >Java >java教程 >如何在 Android 中使用 Volley 發出有效的 POST 多部分請求?

如何在 Android 中使用 Volley 發出有效的 POST 多部分請求?

Linda Hamilton
Linda Hamilton原創
2024-12-01 05:45:10346瀏覽

How to Make Working POST Multipart Requests with Volley in Android?

使用最新API 透過Volley 處理POST 多部分請求

在Android 開發中,發送多部分請求(例如上傳文件和文字資料)是一項共同的任務。雖然 HttpEntity 在較新的 API 版本中不再可用,但仍有一些方法可以使用 Volley 實作多部分請求。

建立基本多部分請求

建立多部分請求,我們可以像這樣擴展 Volley 的 Request類別:

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);
    }
}

建構多部分主體

要建構多部分主體,我們可以使用以下步驟:

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();

在請求中包含多部分主體

一旦建置了多部分主體,我們就可以將其包含在我們的MultipartRequest 實例中,例如so:

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
            }
        });

在請求中加入文字資料

除了圖像數據,您還可以在請求中包含文字數據:

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);
}

將兩個連字符、邊界和lineEnd 替換為您的適當值code.

完整代碼範例

以下程式碼範例顯示了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());
        }

以上是如何在 Android 中使用 Volley 發出有效的 POST 多部分請求?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn