2017-12-27 226 views
0

我只是Android应用程序开发的初学者。如何在Android Volley Library中使用MultiPart上传图像文件阵列

我想使用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张照片)。我想用volley库做完全相同的API调用。

enter image description here enter image description here

回答

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' 

    } 
  • Helper类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); 
         } 
        } 
    } 
    
  • 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.Calling异步

    new registerCall().execute(); 
    
    相关问题