如何使用Android Volley Library中的MultiPart上传图像文件数组

时间:2017-12-27 14:44:42

标签: android android-volley

我只是Android App开发的初学者。

我想使用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;
            }


        };

我收到服务器错误作为回复。

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

在邮递员中,标题和参数是这样的,有一系列图像,你可以在附图中看到(8张照片)。我想使用齐射库进行完全相同的API调用。

enter image description here enter image description here

2 个答案:

答案 0 :(得分:2)

试试这段代码:

我使用此

修复了类似的问题

使用multipart上传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. 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();
      
      }
      

      }

    3. 5.Calling Async

        new registerCall().execute();
      

答案 1 :(得分:0)

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

private dataPartList = ArrayList();

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