5

Ich habe einen Kunden-HTTP-Aufruf funktioniert mit den Standard-Apache-Klassen, aber ich versuche, eine benutzerdefinierte Volley-Klasse zu erstellen, um damit umzugehen. Hier ist der Code für Standard-Aufruf:Problem beim Senden von Multipart-Datei mit Boundary über 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(); 

Nicht sicher, wie der Rest zu tun, aber das ist, was ich für das Volley habe, die nicht funktionieren. Ich habe Multipart vor, aber nicht mit Grenze und in diesem seltsamen Format getan.

Öffentliche Klasse ImageMultiRequest erweitert 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")); 

    } 
} 

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

Lösung auf die Antwort Basierend unter

Hier ist, was ich kam mit, dass für diese gearbeitet und möglicherweise auch andere Probleme mit mehrteiliger Datei, um den Inhalt Körper

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

} 

Antwort

3

eingebettet diese ist mein funktionierender Beispielcode (nur mit kleinen Dateien getestet):

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 danke für die Lösung hat mich eine Menge Zeit gerettet, Prost in Ihrer Ehre! (Ein Glas heben) – JPM

Verwandte Themen