如何post音频和图像作为multipart/formdata原生android?

How to post audio and image as multipart/formdata in native android?

我想post像这样形成数据,

其中,

  1. ApiKey,userid,albumid,music_name,singer_name为key对应的值都是text类型
  2. music_cover和music_file是图像文件和音频文件的键值。

All the values are non nullable. That is, must pass all values to the server to get a success response.

所以,总而言之,我有一堆文本、音频和图像要使用来自 android 的 Web 服务上传到服务器。

我正在使用选择器选择图像和音频,所以我有它们的文件路径。

请指导我完成使用 android 的 multipart 上传音频和图像的过程。

它让我彻夜难眠,但没有任何缓解。

这里我使用 Volley 创建了一个示例 所以首先我们必须构建一个 RestApiMultiPartRequests.class 所以我在这里创建它是这样的

私有 class RestApiMultiPartRequests 扩展请求 {

private final Map<String, String> mStringParts;
private final Map<String, File> mFileParts;
private MultipartEntityBuilder mBuilder;
private final Response.Listener<T> mListener;

public RestApiMultiPartRequests(String url,
                                Map<String, String> stringParts,
                                Map<String, File> fileParts,
                                Response.Listener<T> listener,
                                Response.ErrorListener errorListener) {
    super(Method.POST, url, errorListener);
    mListener = listener;
    mStringParts = stringParts;
    mFileParts = fileParts;
    buildMultipartEntity();
}

private void buildMultipartEntity() {
    if (mBuilder != null) {
        mBuilder = null;
    }
    mBuilder = MultipartEntityBuilder.create();
    mBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    mBuilder.setBoundary("_____" + Long.toString(System.currentTimeMillis()) + "_____");
    mBuilder.setCharset(Consts.UTF_8);
    if (mStringParts != null) {
        for (Map.Entry<String, String> entry : mStringParts.entrySet()) {
            mBuilder.addTextBody(entry.getKey(), entry.getValue(), ContentType.create("text/plain", Charset.forName("UTF-8")));
        }
    }

    Log.e("Size", "Size: " + mFileParts.size());
    for (Map.Entry<String, File> entry : mFileParts.entrySet()) {
        ContentType imageContentType = ContentType.create("image/*");//MULTIPART_FORM_DATA;
        Log.d("", "Key " + entry.getKey());
        Log.d("", "Value " + entry.getValue());
        Log.d("", "Name " + entry.getValue().getName());
        //"userfile"
        mBuilder.addBinaryBody(entry.getKey(), entry.getValue(), imageContentType, entry.getValue().getName());
    }
}

@Override
public String getBodyContentType() {
    return mBuilder.build().getContentType().getValue();
}

@Override
public byte[] getBody() {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    try {
        mBuilder.build().writeTo(bos);
    } catch (IOException e) {
        e.printStackTrace();
    }

    return bos.toByteArray();
}


public HttpEntity getEntity() {
    return mBuilder.build();
}


@SuppressWarnings("unchecked")
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
    try {
        String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
        return (Response<T>) Response.success(jsonString, HttpHeaderParser.parseCacheHeaders(response));
    } catch (UnsupportedEncodingException e) {
        return Response.error(new ParseError(e));
    }
}

@Override
protected void deliverResponse(T response) {
    mListener.onResponse(response);

}


}

使用这个 class 我们可以构建这样的请求

 private void UploadImage() {

    ServiceCall.RestApiMultiPartRequests<String> restApiMultiPartRequest =
            new ServiceCall.RestApiMultiPartRequests<String>(url/*YOUR SERVICE URL*/, hashMap /* HASHMAP OF STRING */, fileparts  /*HASH MAP OF FILE AND STRING */, new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                   /*   HANDEL YOUR SUCCESS RESPONSE **/
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    // Handle your error types accordingly.For Timeout & No
                    // connection error, you can show 'retry' button.
                    // For AuthFailure, you can re login with user
                    // credentials.
                    // For ClientError, 400 & 401, Errors happening on
                    // client side when sending api request.
                    // In this case you can check how client is forming the
                    // api and debug accordingly.
                    // For ServerError 5xx, you can do retry or handle
                    // accordingly.


                      /**  HANDLE YOUR ERRORS */
                }
            }) {

                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    Map<String, String> params = new HashMap<String, String>();
                    params.put("Authorization","YOUR AUTHANTICATION TOKEN IF REQUIRED");
                    return params;
                }

                @Override
                protected Map<String, String> getParams() throws AuthFailureError {
                    Map<String, String> params = new HashMap<String, String>();
                    return params;
                }
            };

    restApiMultiPartRequest.setRetryPolicy(new DefaultRetryPolicy(0, 1, 2));//10000
    VOLLEY_INSTANCE.addToRequestQueue(restApiMultiPartRequest);
}

这里hashmapHashMap<String, String> hashMap filepartsHashMap<String, File> fileparts;

所以带StringkeyStringvalue的参数加入hashmap 和带有 String 键和 File Value 的参数添加到 fileparts