【问题标题】:How to upload array of image files using MultiPart in Android Volley Library如何在 Android Volley 库中使用 MultiPart 上传图像文件数组
【发布时间】:2020-04-29 23:33:04
【问题描述】:

我只是 Android 应用开发的初学者。

我想使用 Android Volley 库上传图片文件。

我使用了在某个博客的某个地方找到的这个帮助类。:

    public class VolleyMultiPartRequest extends Request<NetworkResponse> {

    private final String twoHyphens = "--";
    private final String lineEnd = "\r\n";
    private final String boundary = "apiclient-" + System.currentTimeMillis();

    private Response.Listener<NetworkResponse> mListener;
    private Response.ErrorListener mErrorListener;
    private Map<String, String> mHeaders;

    SharedPreferencesManager sharedPreferencesManager =null;

    public VolleyMultiPartRequest(int method, String url,
                                  Response.Listener<NetworkResponse> listener,
                                  Response.ErrorListener errorListener, Context context) {
        super(method, url, errorListener);
        this.mListener = listener;
        this.mErrorListener = errorListener;
        this.sharedPreferencesManager = new SharedPreferencesManager(context);
    }


   @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Accept", "application/json");
        headers.put("Authorization", "Bearer " + sharedPreferencesManager.retreiveString(AppText.ACCESS_TOKEN));
        headers.put("Content-Type", "multipart/form-data");
        return headers;
    }
    @Override
    public String getBodyContentType() {
        return "multipart/form-data;boundary=" + boundary;
    }

    @Override
    public byte[] getBody() throws AuthFailureError {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(bos);

        try {
            // populate text payload
            Map<String, String> params = getParams();
            if (params != null && params.size() > 0) {
                textParse(dos, params, getParamsEncoding());
            }

            // populate data byte payload
            Map<String, DataPart> data = getByteData();
            if (data != null && data.size() > 0) {
                dataParse(dos, data);
            }

            // close multipart form data after text and file data
            dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

            return bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    protected Map<String, DataPart> getByteData() throws AuthFailureError {
        return null;
    }

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


    private void textParse(DataOutputStream dataOutputStream, Map<String, String> params, String encoding) throws IOException {
        try {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                buildTextPart(dataOutputStream, entry.getKey(), entry.getValue());
            }
        } catch (UnsupportedEncodingException uee) {
            throw new RuntimeException("Encoding not supported: " + encoding, uee);
        }
    }


    private void dataParse(DataOutputStream dataOutputStream, Map<String, DataPart> data) throws IOException {
        for (Map.Entry<String, DataPart> entry : data.entrySet()) {
            buildDataPart(dataOutputStream, entry.getValue(), entry.getKey());
        }
    }


    private void buildTextPart(DataOutputStream dataOutputStream, String parameterName, String parameterValue) throws IOException {
        dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
        dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + parameterName + "\"" + lineEnd);
        dataOutputStream.writeBytes(lineEnd);
        dataOutputStream.writeBytes(parameterValue + lineEnd);
    }

    private void buildDataPart(DataOutputStream dataOutputStream, DataPart dataFile, String inputName) throws IOException {
        dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
        dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" +
                inputName + "\"; filename=\"" + dataFile.getFileName() + "\"" + lineEnd);
        if (dataFile.getType() != null && !dataFile.getType().trim().isEmpty()) {
            dataOutputStream.writeBytes("Content-Type: " + dataFile.getType() + lineEnd);
        }
        dataOutputStream.writeBytes(lineEnd);

        ByteArrayInputStream fileInputStream = new ByteArrayInputStream(dataFile.getContent());
        int bytesAvailable = fileInputStream.available();

        int maxBufferSize = 1024 * 1024;
        int bufferSize = Math.min(bytesAvailable, maxBufferSize);
        byte[] buffer = new byte[bufferSize];

        int bytesRead = fileInputStream.read(buffer, 0, bufferSize);

        while (bytesRead > 0) {
            dataOutputStream.write(buffer, 0, bufferSize);
            bytesAvailable = fileInputStream.available();
            bufferSize = Math.min(bytesAvailable, maxBufferSize);
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
        }

        dataOutputStream.writeBytes(lineEnd);
    }

    public class DataPart {
        private String fileName;
        private byte[] content;
        private String type;

        public DataPart() {
        }

        public DataPart(String name, byte[] data) {
            fileName = name;
            content = data;
        }

        String getFileName() {
            return fileName;
        }

        byte[] getContent() {
            return content;
        }

        String getType() {
            return type;
        }

    }
}

并像这样调用这个助手:

 VolleyMultiPartRequest volleyMultipartRequest = new VolleyMultiPartRequest(Request.Method.POST, Api.UPLOAD_FILE,
                new Response.Listener<NetworkResponse>() {
                    @Override
                    public void onResponse(NetworkResponse response) {
                        try {
                            JSONObject obj = new JSONObject(new String(response.data));
                            Toast.makeText(context, obj.getString("message"), Toast.LENGTH_SHORT).show();
                            successCallBack.onSuccess(obj);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(context, error.getMessage(), Toast.LENGTH_SHORT).show();
                        try {
                            errorCallBack.onError(new JSONObject(""));
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }, context) {

            /*
            * If you want to add more parameters with the image
            * you can do it here
            * here we have only one parameter with the image
            * which is tags
            * */
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<>();
                params.put("file_for", "post");
                params.put("file_type", "image");
                return params;
            }

            /*
            * Here we are passing image by renaming it with a unique name
            * */
            @Override
            protected Map<String, DataPart> getByteData() {
                Map<String, DataPart> params = new HashMap<>();
                long imagename = System.currentTimeMillis();
                params.put("images[]", new DataPart(imagename + ".png", getFileDataFromDrawable(bitmap)));
                return params;
            }


        };

我收到服务器错误作为响应。

我尝试了不同的教程,但没有找到确切的方法和简单的解决方案。

在邮递员中,headers 和 params 是这样的,有一系列图片,你可以在附加的照片中看到(8 张照片)。我想使用 volley 库进行完全相同的 API 调用。

【问题讨论】:

    标签: android android-volley


    【解决方案1】:

    试试这个代码:

    我用这个解决了类似的问题

    使用多部分上传multiple files in array

    1. 添加依赖

      compile 'org.apache.httpcomponents:httpcore:4.2.4'
      compile 'org.apache.httpcomponents:httpmime:4.2'
      compile 'com.mcxiaoke.volley:library:1.0.19'
      

    2.在gradle中添加

        defaultConfig {
                useLibrary 'org.apache.http.legacy'
    
        }
    
    1. 帮助类AndroidMultiPartEntity.java

      public class AndroidMultiPartEntity extends MultipartEntity
      
      {
      
          private final ProgressListener listener;
      
          public AndroidMultiPartEntity(final ProgressListener listener) {
              super();
              this.listener = listener;
          }
      
          public AndroidMultiPartEntity(final HttpMultipartMode mode, final ProgressListener listener) {
              super(mode);
              this.listener = listener;
          }
      
          public AndroidMultiPartEntity(HttpMultipartMode mode, final String boundary,
                                        final Charset charset, final ProgressListener listener) {
              super(mode, boundary, charset);
              this.listener = listener;
          }
      
          @Override
          public void writeTo(final OutputStream outstream) throws IOException {
              super.writeTo(new CountingOutputStream(outstream, this.listener));
          }
      
          public interface ProgressListener {
              void transferred(long num);
          }
      
          public static class CountingOutputStream extends FilterOutputStream {
      
              private final ProgressListener listener;
              private long transferred;
      
              public CountingOutputStream(final OutputStream out,
                                          final ProgressListener listener) {
                  super(out);
                  this.listener = listener;
                  this.transferred = 0;
              }
      
              public void write(byte[] b, int off, int len) throws IOException {
                  out.write(b, off, len);
                  this.transferred += len;
                  this.listener.transferred(this.transferred);
              }
      
              public void write(int b) throws IOException {
                  out.write(b);
                  this.transferred++;
                  this.listener.transferred(this.transferred);
              }
          }
      }
      
    2. API调用方式

      private class registerCall extends AsyncTask<Void, Integer, String> {
      @Override
      protected void onPreExecute() {
          super.onPreExecute();
      }
      
      @Override
      protected void onProgressUpdate(Integer... progress) {
      }
      
      @Override
      protected String doInBackground(Void... params) {
          return registerMultipartCall();
      }
      
      private String registerMultipartCall() {
          String responseString = null;
          HttpClient httpclient = new DefaultHttpClient();
          HttpPost httppost = new HttpPost("URL");  //UPLOAD URL
          try {
              AndroidMultiPartEntity entity = new AndroidMultiPartEntity(new AndroidMultiPartEntity.ProgressListener() {
                  @Override
                  public void transferred(long num) {
                  }
              });
      
              File sourceFile = new File(filePath);
              File sourceFile2 = new File(filePath);
      
              entity.addPart("images[0]",  new FileBody(sourceFile));
              entity.addPart("images[1]",  new FileBody(sourceFile2));
              //Do your stuff multiple files
      
              entity.addPart("file_type", new StringBody("image");
              entity.addPart("file_form", new StringBody("post");
      
              httppost.addHeader("Accept","application/json");
              httppost.addHeader("Content-Type", "multipart/form-data");
              httppost.addHeader("Authorization", "Bearer " + sharedPreferencesManager.retreiveString(AppText.ACCESS_TOKEN));
      
      
              httppost.setEntity(entity);
      
              // Making server call
              HttpResponse response = httpclient.execute(httppost);
              HttpEntity r_entity = response.getEntity();
      
              int statusCode = response.getStatusLine().getStatusCode();
              if (statusCode == 200) {
                  // Server response
                  statusCode = 200;
                  responseString = EntityUtils.toString(r_entity);
              } else {
                  statusCode = 200;
                  responseString = "Error occurred! Http Status Code: " + statusCode;
              }
      
          } catch (ClientProtocolException e) {
              responseString = e.toString();
          } catch (IOException e) {
              responseString = e.toString();
          }
      
          return responseString;
      
      }
      
      @Override
      protected void onPostExecute(String result) {
          hideProgressDialog();
      
      }
      

      }

    5.调用异步

      new registerCall().execute();
    

    【讨论】:

      【解决方案2】:

      只需用以下代码替换 getByteData() 方法:

      私有数据PartList = ArrayList();

      @Override
      protected Map<String, List<DataPart>> getByteDataList(){
       Map<String, List<DataPart>> params = new HashMap<>();
        params.put("yourKey","dataPartList");
          return params
      }
      

      【讨论】:

        猜你喜欢
        • 2015-11-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-22
        • 1970-01-01
        • 2019-08-10
        • 2018-07-28
        相关资源
        最近更新 更多