Last active
November 20, 2019 15:45
-
-
Save HussainDerry/0b31063b0c9dcb1cbaec to your computer and use it in GitHub Desktop.
Multipart request for Google's Volley using Square's OkHttp.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.android.volley.AuthFailureError; | |
import com.android.volley.DefaultRetryPolicy; | |
import com.android.volley.NetworkResponse; | |
import com.android.volley.Request; | |
import com.android.volley.Response; | |
import com.android.volley.RetryPolicy; | |
import com.android.volley.VolleyLog; | |
import com.android.volley.toolbox.HttpHeaderParser; | |
import com.squareup.okhttp.Headers; | |
import com.squareup.okhttp.MediaType; | |
import com.squareup.okhttp.MultipartBuilder; | |
import com.squareup.okhttp.RequestBody; | |
import android.util.Log; | |
import java.io.ByteArrayOutputStream; | |
import java.io.File; | |
import java.io.IOException; | |
import java.io.UnsupportedEncodingException; | |
import java.util.HashMap; | |
import java.util.Map; | |
import okio.Buffer; | |
/** | |
* Multipart request for Google's Volley using Square's OkHttp. | |
* @author Hussain Al-Derry | |
* @version 1.0 | |
* */ | |
public class VolleyMultipartRequest extends Request<String> { | |
/* Used for debugging */ | |
private static final String TAG = VolleyMultipartRequest.class.getSimpleName(); | |
/* MediaTypes */ | |
public static final MediaType MEDIA_TYPE_JPEG = MediaType.parse("image/jpeg"); | |
public static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png"); | |
public static final MediaType MEDIA_TYPE_TEXT_PLAIN = MediaType.parse("text/plain"); | |
private MultipartBuilder mBuilder = new MultipartBuilder(); | |
private final Response.Listener<String> mListener; | |
private RequestBody mRequestBody; | |
public VolleyMultipartRequest(String url, | |
Response.ErrorListener errorListener, | |
Response.Listener<String> listener) { | |
super(Method.POST, url, errorListener); | |
mListener = listener; | |
mBuilder.type(MultipartBuilder.FORM); | |
} | |
/** | |
* Adds a collection of string values to the request. | |
* @param mParams {@link HashMap} collection of values to be added to the request. | |
* */ | |
public void addStringParams(HashMap<String, String> mParams){ | |
for (Map.Entry<String, String> entry : mParams.entrySet()) { | |
mBuilder.addPart( | |
Headers.of("Content-Disposition", "form-data; name=\"" + entry.getKey() + "\""), | |
RequestBody.create(MEDIA_TYPE_TEXT_PLAIN, entry.getValue())); | |
} | |
} | |
/** | |
* Adds a single value to the request. | |
* @param key String - the field name. | |
* @param value String - the field's value. | |
* */ | |
public void addStringParam(String key, String value) { | |
mBuilder.addPart( | |
Headers.of("Content-Disposition", "form-data; name=\"" + key + "\""), | |
RequestBody.create(MEDIA_TYPE_TEXT_PLAIN, value)); | |
} | |
/** | |
* Adds a binary attachment to the request. | |
* @param content_type {@link MediaType} - the type of the attachment. | |
* @param key String - the attachment field name. | |
* @param value {@link File} - the file to be attached. | |
* */ | |
public void addAttachment(MediaType content_type, String key, File value){ | |
mBuilder.addFormDataPart("file", key, RequestBody.create(content_type, value)); | |
} | |
/** | |
* Builds the request. | |
* Must be called before adding the request to the Volley request queue. | |
* */ | |
public void buildRequest(){ | |
mRequestBody = mBuilder.build(); | |
} | |
@Override | |
public String getBodyContentType() { | |
return mRequestBody.contentType().toString(); | |
} | |
@Override | |
public byte[] getBody() throws AuthFailureError { | |
Buffer buffer = new Buffer(); | |
try | |
{ | |
mRequestBody.writeTo(buffer); | |
} catch (IOException e) { | |
Log.e(TAG, e.toString()); | |
VolleyLog.e("IOException writing to ByteArrayOutputStream"); | |
} | |
return buffer.readByteArray(); | |
} | |
@Override | |
protected Response<String> parseNetworkResponse(NetworkResponse response) { | |
String parsed; | |
try { | |
parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); | |
} catch (UnsupportedEncodingException e) { | |
parsed = new String(response.data); | |
} | |
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); | |
} | |
@Override | |
public Request<?> setRetryPolicy(RetryPolicy retryPolicy) { | |
return super.setRetryPolicy(retryPolicy); | |
} | |
@Override | |
protected void deliverResponse(String response) { | |
if (mListener != null) { | |
mListener.onResponse(response); | |
} | |
} | |
} |
@tsherdiwala interesting point, never faced that issue before ... even though I've stopped using Google's Volley sometime ago, I'll still look into this matter.
Hi, @HussainDerry I tried your above method but I faced this error "multipart requests must contain at least one part" while using okHttp multipart body with the volley.
Please help, TIA.
Please changes with latest implementation "com.squareup.okhttp3:okhttp:4.0.1", Some methods not found "MultipartBuilder", new Buffer()
I want to thank you for your work It helped me a lot.
Thank you So Much!
Jazak' Allah
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just concerned that will this not throw an Out Of Memory exception when all of the request body is assigned into a buffer when getBody() is called.