5

Ho una chiamata HTTP dei clienti che utilizza le classi standard di apache ma sto cercando di creare una classe Volley personalizzata per gestirlo. Ecco il codice per la chiamata di serie:Problemi nell'invio di file multipart con Boundary via Volley

HttpURLConnection conn = (HttpURLConnection) new URL(strUrl).openConnection(); 
conn.setDoOutput(true); 
conn.setDoInput(true); 
conn.setConnectTimeout(30000); 
conn.setUseCaches(true); 
conn.setRequestMethod("POST"); 
conn.setRequestProperty("Authorization", "Token " + m_apiKey); 
conn.setRequestProperty("Accept", "text/plain , application/json"); 
conn.setRequestProperty("Connection", "Keep-Alive"); 
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + strBoundary); 
conn.connect(); 


// **** Start content wrapper: 
DataOutputStream request = new DataOutputStream(conn.getOutputStream()); 

request.writeBytes("\r\n--" + strBoundary + "\r\n"); 
request.writeBytes("Content-Disposition: form-data; name=\"" + attachmentName + "\";filename=\"" + imageFileName + "\"" + "\r\n"); 
request.writeBytes("Content-Type: image/jpeg " + "\r\n"); 
request.writeBytes("\r\n"); 
request.write(baos.toByteArray()); 

// **** End content wrapper: 
request.writeBytes("\r\n--"+ strBoundary + "--\r\n"); 

// Flush output buffer: 
request.flush();request.close(); 

Non sai come fare il resto, ma questo è quello che ho per il Volley che non funziona. Ho fatto Multipart prima, ma non con i confini e in questo strano formato.

public class ImageMultiRequest estende StringRequest { final String BOUNDARY = "something"; final String crlf = "\ r \ n"; final String twoHyphens = "-";

private final MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); 

private Response.Listener<String> mListener = null; 
private Response.ErrorListener mEListener; 
// 
private final File mFilePart; 
private Map<String, String> parameters; 
private Map<String, String> header; 
MultipartEntity entity = new MultipartEntity(); 
protected String apiKey; 
ByteArrayOutputStream bos; 

public ImageMultiRequest(String apiKey, String url, Listener<String> rListener, ErrorListener eListener, File file) { 
    super(Method.POST, url, rListener, eListener); 
    setShouldCache(false); 
    this.apiKey = apiKey; 
    this.bos = bos; 
    mListener = rListener; 
    mEListener = eListener; 
    mFilePart = file; 
    entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); 
    entityBuilder.setBoundary(BOUNDARY); 
    buildMultipartEntity(); 
} 

@Override 
public String getBodyContentType() { 
    return "multipart/form-data; boundary=" + BOUNDARY + "; charset=utf-8"; 
} 

/** 
* Overrides the base class to add the Accept: application/json header 
*/ 
@Override 
public Map<String, String> getHeaders() throws AuthFailureError { 

    Map<String, String> headers = super.getHeaders(); 

    if (headers == null || headers.equals(Collections.emptyMap())) { 
     headers = new HashMap<String, String>(); 
    } 
    headers.put("Content-Type", "multipart/form-data;boundary=" + BOUNDARY+ "; charset=utf-8"); 
    headers.put("Connection", "Keep-Alive"); 
    headers.put("Accept", "text/plain , application/json"); 
    headers.put("Authorization", "Token " + apiKey); 
    return headers; 
} 

@Override 
public byte[] getBody() throws AuthFailureError { 
    buildMultipartEntity(); 

    ByteArrayOutputStream bos = new ByteArrayOutputStream(); 

    try { 
     entityBuilder.build().writeTo(bos); 
    } catch (IOException e) { 
     VolleyLog.e("IOException writing to ByteArrayOutputStream"); 
    } 
    return bos.toByteArray(); 
} 

private void buildMultipartEntity() { 
    ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
    entityBuilder.addPart("Content-Type: image/jpeg " + crlf + crlf, new ByteArrayBody(bos.toByteArray(), "car")); 

    } 
} 

=========================================== ======

soluzione basata sulla risposta qui sotto

Ecco cosa mi è venuta che ha lavorato per questo e forse altri problemi con file di multipart incorporato il corpo Content

package com.cars.android.common.volley; 

import com.android.volley.AuthFailureError; 
import com.android.volley.Response; 
import com.android.volley.Response.ErrorListener; 
import com.android.volley.Response.Listener; 
import com.android.volley.VolleyLog; 
import com.android.volley.toolbox.StringRequest; 

import org.apache.http.HttpEntity; 
import org.apache.http.entity.ContentType; 
import org.apache.http.entity.mime.HttpMultipartMode; 
import org.apache.http.entity.mime.MultipartEntity; 
import org.apache.http.entity.mime.MultipartEntityBuilder; 

import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.IOException; 
import java.util.Collections; 
import java.util.HashMap; 
import java.util.Map; 

public class ImageMultiRequest extends StringRequest { 
    final String BOUNDARY = "myboundary"; 

    private final MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); 
    HttpEntity entity = new MultipartEntity(); 

    private Response.Listener<String> mListener = null; 
    private Response.ErrorListener mEListener; 
    // 
    private final File mFilePart; 
    protected String apiKey; 

    public ImageMultiRequest(String apiKey, String url, Listener<String> rListener, ErrorListener eListener, File file) { 
     super(Method.POST, url, rListener, eListener); 
     setShouldCache(false); 
     this.apiKey = apiKey; 
     mListener = rListener; 
     mEListener = eListener; 
     mFilePart = file; 
     entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); 
     entityBuilder.setBoundary(BOUNDARY); 

     ContentType contentType = ContentType.create("image/png"); 
     entityBuilder.addBinaryBody("file", file, contentType, "car"); 
     entity = entityBuilder.build(); 
    } 

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

    /** 
    * Overrides the base class to add the Accept: application/json header 
    */ 
    @Override 
    public Map<String, String> getHeaders() throws AuthFailureError { 

     Map<String, String> headers = super.getHeaders(); 

     if (headers == null || headers.equals(Collections.emptyMap())) { 
      headers = new HashMap<String, String>(); 
     } 
     headers.put("Content-Type", "multipart/form-data;boundary=" + BOUNDARY+ "; charset=utf-8"); 
     headers.put("Connection", "Keep-Alive"); 
     headers.put("Accept", "text/plain , application/json"); 
     headers.put("Authorization", "Token " + apiKey); 
     return headers; 
    } 

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

     try { 
      entity.writeTo(bos); 
     } catch (IOException e) { 
      VolleyLog.e("IOException writing to ByteArrayOutputStream"); 
     } 
     return bos.toByteArray(); 
    } 

} 

risposta

3

questo è il mio codice di esempio funzionante (testato solo con file di piccole dimensioni):

public class FileUploadActivity extends Activity { 

    private final Context mContext = this; 
    HttpEntity httpEntity; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_file_upload); 

     Drawable drawable = getResources().getDrawable(R.drawable.ic_action_home); 
     if (drawable != null) { 
      Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); 
      ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
      bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); 
      final byte[] bitmapdata = stream.toByteArray(); 
      String url = "http://10.0.2.2/api/fileupload"; 
      MultipartEntityBuilder builder = MultipartEntityBuilder.create(); 
      builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); 

      // Add binary body 
      if (bitmapdata != null) { 
       ContentType contentType = ContentType.create("image/png"); 
       String fileName = "ic_action_home.png"; 
       builder.addBinaryBody("file", bitmapdata, contentType, fileName); 
       httpEntity = builder.build(); 

       MyRequest myRequest = new MyRequest(Request.Method.POST, url, new Response.Listener<NetworkResponse>() { 
        @Override 
        public void onResponse(NetworkResponse response) { 
         try {        
          String jsonString = new String(response.data, 
            HttpHeaderParser.parseCharset(response.headers)); 
          Toast.makeText(mContext, jsonString, Toast.LENGTH_SHORT).show(); 
         } catch (Exception e) { 
          e.printStackTrace(); 
         } 
        } 
       }, new Response.ErrorListener() { 
        @Override 
        public void onErrorResponse(VolleyError error) { 
         Toast.makeText(mContext, error.toString(), Toast.LENGTH_SHORT).show();       
        } 
       }) { 
        @Override 
        public String getBodyContentType() { 
         return httpEntity.getContentType().getValue(); 
        } 

        @Override 
        public byte[] getBody() throws AuthFailureError { 
         ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
         try { 
          httpEntity.writeTo(bos); 
         } catch (IOException e) { 
          VolleyLog.e("IOException writing to ByteArrayOutputStream"); 
         } 
         return bos.toByteArray(); 
        } 
       }; 

       MySingleton.getInstance(this).addToRequestQueue(myRequest); 
      } 
     } 
    } 

    ... 
} 

public class MyRequest extends Request<NetworkResponse> 
+1

Hey, grazie per la soluzione mi ha risparmiato un sacco di tempo, Saluti in tuo onore! (Alzando un bicchiere) – JPM

Problemi correlati