Skip to content

Instantly share code, notes, and snippets.

@HussainDerry
Last active November 20, 2019 15:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save HussainDerry/0b31063b0c9dcb1cbaec to your computer and use it in GitHub Desktop.
Save HussainDerry/0b31063b0c9dcb1cbaec to your computer and use it in GitHub Desktop.
Multipart request for Google's Volley using Square's OkHttp.
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
Copy link

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.

@HussainDerry
Copy link
Author

@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.

@pavithra19
Copy link

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.

@pavankvch
Copy link

Please changes with latest implementation "com.squareup.okhttp3:okhttp:4.0.1", Some methods not found "MultipartBuilder", new Buffer()

@Mr-Ramzan
Copy link

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