Retrofit. java.net.ProtocolException: expected * bytes but received *
Here is what I use for all my requests and have no problems at all. Let me know if it does not work for you. I am assuming POST name for your file is "file".
In the protocol:
@Multipart
@POST
Call<ResponseBody> request(
@Url String url, // Request URL
@PartMap Map<String, String> vars, // POST Strings
@PartMap Map<String, RequestBody> files // POST Files
);
Construct a call:
Map<String, String> vars = new HashMap<>();
Map<String, RequestBody> files = new HashMap<>();
/** Put a string **/
vars.put("name", "value");
/** Put a file **/
String key = String.format(Locale.US, "file\"; filename=\"%s", file.getName());
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
files.put(key, requestBody);
/** Construct the call **/
Call<ResponseBody> call = mProtocol.request(url, vars, files);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.d("Debug", response.body().string());
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
if (call.isCanceled()) Log.d("Debug", "Call Canceled");
else Log.d("Debug", "Call Failed: " + t.toString());
}
});
PS: You can use this piece of code to upload multiple files, since it accepts a map of files rather than a single file.
PS#2: Due to several problems I have had with this method, I had to add the below code to make sure it never sends null or empty map.
if (vars == null) {
vars = new HashMap<>();
vars.put("01110011", "01101101"); // put whatever you want
}
if (files == null) files = new HashMap<>();
I have encountered the same issue and solved by creating a temporary file before upload it.
In Kotlin.
fun createTemoraryFile(context: Context, uri: Uri): File {
val inputStream = context.contentResolver.openInputStream(uri)
val f = createTempFile(
directory = context.cacheDir
)
inputStream.copyTo(f.outputStream())
return f
}
And after upload finished, I deleted the temporary file.
After studying for a while the problem I've realized that the content of the file was always changing (as it is the output of a sensor).
It means that the file that is checked for the HEAD and the file for the BODY may not contain the same data (therefore different length), which caused the mismatch.
I solved this creating a copy of the file and sending it (the copy) instead of the original file.
I faced this problem when I was trying to upload a recording. I solved it by stopping the recording process before calling the web service to upload the file.
objMediaRecorder.stop();
objMediaRecorder.release();
objMediaRecorder = null;