I have an app the stores photos with Room in the database I store a image in a byte[].
I have an activity where when I press the button upload the images through Retrofit but when I start to upload, the app throws an error.
Here is the code of the function to upload the images;
for (int i = 0; i < evidences.size(); i++) {
order = evidences.get(i).getMobmx();
ticketEv = evidences.get(i).getTicketEv();
Toast.makeText(this, "MOBMX: " + order, Toast.LENGTH_SHORT).show();
File filesDir = this.getFilesDir();
File photo = new File(filesDir, "" + order + ".jpeg");
FileOutputStream fos;
try {
fos = new FileOutputStream(photo);
fos.write(ticketEv);
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), photo);
MultipartBody.Part body = MultipartBody.Part.createFormData("image", photo.getName(), requestFile);
apiService.uploadPod(getString(R.string.uploadPodOfflinePetition), body, RequestBody.create(MediaType.parse("text/plain"), order))
.enqueue(new Callback<UserData>() {
#Override
public void onResponse(Call<UserData> call, Response<UserData> response) {
if (response.isSuccessful()) {
if (response.body() != null) {
try {
processResult(response.body().getMsg(), response.body().getData());
} catch (Exception e) {
Toast.makeText(OnlineEvidenceActivity.this, "Error procesando la respuesta del servidor, por favor intente de nuevo", Toast.LENGTH_SHORT).show();
}
}
} else {
try {
String erroResp = response.errorBody().string();
Log.i("ERROR", erroResp);
processError(erroResp);
} catch (IOException | JSONException e) {
e.printStackTrace();
Toast.makeText(OnlineEvidenceActivity.this, "Error al procesar respuesta", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onFailure(Call<UserData> call, Throwable t) {
//RequestFailHandler.handleFail(OnlineEvidenceActivity.this, t);
Log.e("ERROREVIDENCIA", t.getMessage());
}
});
}
Here is the function when the response is successful:
private void processResult(String msg, Object data) {
StatusPODS statusPODS = new StatusPODS();
if (msg.equals("ok")) {
Toast.makeText(this, "Procesar evidencia", Toast.LENGTH_SHORT).show();
statusPODS.setMobmx(order);
statusPODS.setStatus("Exitoso");
evidenceDAO.insertStatus(statusPODS);
//evidenceDAO.deleteRow(order);
} else if (msg.equals("warning")) {
Toast.makeText(this, "" + data, Toast.LENGTH_SHORT).show();
statusPODS.setMobmx(order);
statusPODS.setStatus("Warning");
evidenceDAO.insertStatus(statusPODS);
//evidenceDAO.deleteRow(order);
} else {
//Error
Toast.makeText(this, "" + data, Toast.LENGTH_SHORT).show();
statusPODS.setMobmx(order);
statusPODS.setStatus("Error");
evidenceDAO.insertStatus(statusPODS);
//evidenceDAO.deleteRow(order);
}
}
This is the Service endpoint:
#Multipart
#POST("mobile/uploadpodoffline")
Call<UserData> uploadPod(#Header("petition") String petition,
#Part MultipartBody.Part image,
#Part ("order") RequestBody order);
And finally this is the error when upload the first image:
HTTP FAILED: java.net.ProtocolException: expected 422764 bytes but received 425984
Any solution to upload the images creating a new File and send through the for loop with retrofit (?)
Thanks
Related
I tried to upload a PDF file [Not Image] in PHP API from Android, and I'm getting 400 with this exception:
{"head":{"StatusValue":400,"StatusText":"Failed"},"body":{"Error":"Missing required property fileId"}}
I'm getting 200 request code, when I'm doing in Postman:
Now, Android code:
#Multipart
#POST("eligibity/auth/attachment/upload/add")
Call<ResponseBody> uploadFile(#Part MultipartBody.Part file, #Part("fileName") RequestBody name, #Part("body") JSONObject body);
private void uploadPDF(String path) {
String pdfname = String.valueOf(Calendar.getInstance().getTimeInMillis());
File file = new File(path);
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("fileName", file.getName(), requestBody);
RequestBody filename = RequestBody.create(MediaType.parse("text/plain"), pdfname);
try {
JSONObject sJsonAttachment = new JSONObject();
JSONObject body = new JSONObject();
sJsonAttachment.put("appointmentId", AdapterCollections.clsClaimDiscussionList.get(position).appointment_id);
sJsonAttachment.put("createdBy", Integer.parseInt(preferenceManager.getUserId()));
sJsonAttachment.put("customerId", Integer.parseInt(preferenceManager.getCustomerId()));
sJsonAttachment.put("encounterId", AdapterCollections.clsClaimDiscussionList.get(position).encounter_id);
sJsonAttachment.put("expiryDate", Utility.getCurrentDate("MM-DD-YY"));
sJsonAttachment.put("fbType", 4);
sJsonAttachment.put("fileId", 0);
sJsonAttachment.put("fileName", "name");
sJsonAttachment.put("insTpaPatId", 0);
sJsonAttachment.put("isActive", 1);
sJsonAttachment.put("messageId", AdapterCollections.clsClaimDiscussionList.get(position).log_messages.get(position).log_id);
sJsonAttachment.put("patientId", AdapterCollections.clsClaimDiscussionList.get(position).patient_id);
sJsonAttachment.put("recType", "");
sJsonAttachment.put("reportDate", Utility.getCurrentDate("DD-MM-YYYY"));
sJsonAttachment.put("siteId", Integer.parseInt(preferenceManager.getSiteId()));
sJsonAttachment.put("type", 4);
sJsonAttachment.put("uploadDate", Utility.getCurrentDate("MMDDYY"));
// body.put("body", sJsonAttachment);
ApiCall apiCall = RetrofitService.createService(SCMS_BASE_URL, ApiCall.class);
assert apiCall != null;
apiCall.uploadFile(fileToUpload, filename, sJsonAttachment).enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(#NotNull Call<ResponseBody> call, #NotNull Response<ResponseBody> response) {
try {
showLog("STATUS: " + response.code());
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onFailure(#NotNull Call<ResponseBody> call, #NotNull Throwable t) {
showLog("FAILED: "+ t.getMessage());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
I know that I'm doing somewhere small mistakes, but not able to spot that.
If I used part then this error: Missing required property fileId, and if I use query then this error: must be object.
Update
Regarding Path:
provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="/storage/emulated/0" path="."/>
</paths>
Intent to open PDF chooser:
private void fileDialog() {
Intent intent = new Intent().setType("application/pdf").setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(Intent.createChooser(intent, "Select PDF file"), 123);
}
I followed this https://stackoverflow.com/a/62830720/12630878 answer to getPath, but, I'm NOT getting path properly.
Higher version means: 28 to 30
Higher Version URI:
URI: content://com.android.providers.media.documents/document/document%3A31
FROM RECENT, If I'll choose PDF, then cursor is returning null:
if (cursor.moveToFirst()) {
return cursor.getString(column_index);
}
FROM DOWNLOADS, if I'll choose PDF, then NumberFormatException coming on this line:
URI: content://com.android.providers.downloads.documents/document/msf%3A27
Exception: java.lang.NumberFormatException: For input string: "msf:27"
LINE NO: Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));
FileUtils class: https://drive.google.com/file/d/1S5-Sdp_CCSXXsOsZxwuhv0F5_CtH2EQO/view?usp=sharing
Search this method where I'm getting Path:
public static File getFile(Context context, Uri uri) {
if (uri != null) {
String path = getPathForAllVersion(context, uri);
// String path = getFilePathFromURI(context, uri);
showLog("isPATH: " + path);
if (checkNull(path) && isLocal(path)) {
return new File(path);
}
}
return null;
}
You api accept only two parameters but you passed three parameters that's why you getting error.
so API method should be
#Multipart
#POST("eligibity/auth/attachment/upload/add")
Call<ResponseBody> uploadFile(
#Part("body") RequestBody description,
#Part MultipartBody.Part file
);
And update your uploadPDF() like below
private void uploadPDF(String path) {
//json data
JSONObject sJsonAttachment = new JSONObject();
JSONObject body = new JSONObject();
sJsonAttachment.put("appointmentId", AdapterCollections.clsClaimDiscussionList.get(position).appointment_id);
sJsonAttachment.put("createdBy", Integer.parseInt(preferenceManager.getUserId()));
sJsonAttachment.put("customerId", Integer.parseInt(preferenceManager.getCustomerId()));
sJsonAttachment.put("encounterId", AdapterCollections.clsClaimDiscussionList.get(position).encounter_id);
sJsonAttachment.put("expiryDate", Utility.getCurrentDate("MM-DD-YY"));
sJsonAttachment.put("fbType", 4);
sJsonAttachment.put("fileId", 0);
sJsonAttachment.put("fileName", "name");
sJsonAttachment.put("insTpaPatId", 0);
sJsonAttachment.put("isActive", 1);
sJsonAttachment.put("messageId", AdapterCollections.clsClaimDiscussionList.get(position).log_messages.get(position).log_id);
sJsonAttachment.put("patientId", AdapterCollections.clsClaimDiscussionList.get(position).patient_id);
sJsonAttachment.put("recType", "");
sJsonAttachment.put("reportDate", Utility.getCurrentDate("DD-MM-YYYY"));
sJsonAttachment.put("siteId", Integer.parseInt(preferenceManager.getSiteId()));
sJsonAttachment.put("type", 4);
sJsonAttachment.put("uploadDate", Utility.getCurrentDate("MMDDYY"));
// create RequestBody instance from file
File file=new File(path);
RequestBody requestFile =
RequestBody.create(
MediaType.parse(Files.probeContentType(file.toPath()))),
file
);
// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part fileBody =
MultipartBody.Part.createFormData("fileName", file.getName(), requestFile);
// add another part within the multipart request
RequestBody bodyJsonAttachment =
RequestBody.create(
okhttp3.MultipartBody.FORM, sJsonAttachment.toString());
ApiCall apiCall = RetrofitService.createService(SCMS_BASE_URL, ApiCall.class);
assert apiCall != null;
apiCall.uploadFile(fileBody, bodyJsonAttachment).enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(#NotNull Call<ResponseBody> call, #NotNull Response<ResponseBody> response) {
try {
showLog("STATUS: " + response.code());
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onFailure(#NotNull Call<ResponseBody> call, #NotNull Throwable t) {
showLog("FAILED: "+ t.getMessage());
}
});
}
Note : if you getting warning error on mime type, update it
If you are using multipart then pass all the field in Multipart just like this.
Declare method in Api interface just like this. Only one MultipartBody field.
#Multipart
#POST("eligibity/auth/attachment/upload/add")
Call<ResponseBody> uploadFile(#Body MultipartBody body);
Create MultipartBody.Builder add your and your field in it.
MultipartBody.Builder requestBodyBuilde = MultipartBody.Builder().setType(MultipartBody.FORM);
//adding image in multipart
File file = File(selected_file_path);
RequestBody fileBody = ProgressRequestBody(file, this);
requestBodyBuilde.addFormDataPart("fileName", file.name, fileBody);
//add your other field just like this
requestBodyBuilde.addFormDataPart("body", sJsonAttachment );
ApiCall apiCall = RetrofitService.createService(SCMS_BASE_URL, ApiCall.class);
assert apiCall != null;
//Note here we will pass only one parameter that is multipartBody
apiCall.uploadFile(requestBodyBuilde.build()).enqueue(new
Callback<ResponseBody>() {
#Override
public void onResponse(#NotNull Call<ResponseBody> call, #NotNull Response<ResponseBody> response) {
try {
showLog("STATUS: " + response.code());
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onFailure(#NotNull Call<ResponseBody> call, #NotNull Throwable t) {
showLog("FAILED: "+ t.getMessage());
}
});
} catch (Exception e) {
e.printStackTrace();
}
My image is not getting upload to server i have searched several links but didn't find the useful way bellow are the codes
RFInterface.java
#Multipart
#POST("compose_notice")
Call<PostNoticeModel> compose_notice(
#Query("apartment_id") String apartment_id,
#Query("subject") String subject,
#Query("descriptions") String descriptions,
#Query("expiry_time") String expiry_time,
#Query("notice_visible_group") String notice_visible_group,
#Query("selectedUser") String selectedUser,
//#Part ("attachmentFile") RequestBody file
//#Part ("attachmentFile\"; filename=\"attachmentFile\" ") RequestBody attachmentFile
#Part MultipartBody.Part attachmentFile
);
here are the code from where i am getting response to rfinterface.java file
btn_submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
get_title = edt_title.getText().toString();
get_description = edt_description.getText().toString();
if(get_expires.equals("Custom")){
get_expires = custom_date.getText().toString();
}
if(get_title.trim().length() == 0){
Toast.makeText(PostNotice.this, "Please enter title", Toast.LENGTH_SHORT).show();
}else if(get_description.trim().length() == 0){
Toast.makeText(PostNotice.this, "Please enter description", Toast.LENGTH_SHORT).show();
}else {
if(finalfile != null) {
reqFile = RequestBody.create(MediaType.parse("multipart/form-data"), finalfile);
body = MultipartBody.Part.createFormData("attachmentFile", finalfile.getName(), reqFile);
// get_titlee =
// RequestBody.create(MediaType.parse("multipart/form-data"), get_title);
}else{
body = null;
}
//Toast.makeText(PostNotice.this, ""+body, Toast.LENGTH_SHORT).show();
RFInterface api = RFClient.getApiService();
Call<PostNoticeModel> call = api.compose_notice(apartment_id, get_title, get_description, get_expires, get_noticevisibility, suserstring, body);
final ProgressDialog progressDoalog;
progressDoalog = new ProgressDialog(PostNotice.this);
progressDoalog.setMessage("Its loading....");
progressDoalog.setTitle("Please wait it take some time ");
// show it
progressDoalog.show();
call.enqueue(new Callback<PostNoticeModel>() {
#Override
public void onResponse(Call<PostNoticeModel> call, Response<PostNoticeModel> response) {
if (response.isSuccessful()) {
getresponse = response.body().getMsg();
Toast.makeText(getApplicationContext(), getresponse, Toast.LENGTH_LONG).show();
progressDoalog.dismiss();
} else {
Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_SHORT).show();
progressDoalog.dismiss();
}
}
#Override
public void onFailure(Call<PostNoticeModel> call, Throwable t) {
progressDoalog.dismiss();
}
});
}
}
});
please tell me where i am doing wrong all things are working properly all the data get inserted in table to compose notice but image is not uploaded image column remain empty.
Use Requesbody
#Multipart
#POST(urlString)
fun addField(#PartMap partMap: Map,
#Part imagefile: MultipartBody.Part?
): Observable
The error happened when i upload a 115KB image file to server.(the most answer of stackoverflow is about download the file.I do not know if it is the same to those)
the error information is below:
onFailure : java.net.ProtocolException: unexpected end of stream
Relevant Code:
public void upLoadImageFile(String uploadUrl, File file, Map<String, String> maps, final HWUploadListener listener) {
final CallbackHandler handler = new CallbackHandler(listener);
try {
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
if (maps == null) {
builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"image\";filename=\"file.jpg\""),
RequestBody.create(MediaType.parse("image/jpeg"), file)).build();
} else {
for (String key : maps.keySet()) {
builder.addFormDataPart(key, maps.get(key));
}
builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"image\";filename=" + file.getName()), RequestBody.create(MediaType.parse("image/jpeg"), file)
);
}
RequestBody body = builder.build();
final Request request = new Request.Builder().url(uploadUrl).post(body).build();
final Call call = mOkHttpClient.newBuilder().writeTimeout(50, TimeUnit.SECONDS).build().newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
UtilUtils1.log("HuowuSdk", "onFailure :" + e.toString());
handler.uploadFailure(e.toString());
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String result = response.body().string();
handler.uploadSuccess(result);
} else {
handler.uploadFailure(response.message());
}
}
});
} catch (Exception e) {
UtilUtils1.log("HuowuSdk", e.toString());
handler.uploadError(e.toString());
}
}
Appreciate your answer!!
Here in this line below you have to increase write timeout because while uploading your write timeout expires that may be the reason so in below line increase writeTimeout limit:
final Call call = mOkHttpClient.newBuilder().writeTimeout(50, TimeUnit.SECONDS).build().newCall(request);
i have urls of i got as response from a volley JsonObectRequest. What i want to be able to do is save those images directly into a folder on my external storage so i don't have to load them from the internet anymore. Please keep in mind that download may also include videos...
//Here is the volley code for retrieving the urls
private static final String endpoint = "http://api.androidhive.info/json/glide.json";
//Code to extract image url
JsonArrayRequest req = new JsonArrayRequest(endpoint,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
pDialog.hide();
images.clear();
for (int i = 0; i < response.length(); i++) {
try {
JSONObject object = response.getJSONObject(i);
Image image = new Image();
image.setName(object.getString("name"));
JSONObject url = object.getJSONObject("url");
image.setSmall(url.getString("small"));
image.setMedium(url.getString("medium"));
image.setLarge(url.getString("large"));
image.setTimestamp(object.getString("timestamp"));
} catch (JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
}
}
mAdapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Error: " + error.getMessage());
pDialog.hide();
}
});
Now, how do i request a download so they files are save in my external using volley. Thank you
public boolean storeImages(Bitmap imageBitmap, String fileName, String dirName, int index) {
File file;
if (isExternalStorageWritable() && isExternalStorageReadable()) {
file = storeImageExternalMemory(dirName, albumName, String.valueOf(index));
}
try {
assert file != null;
FileOutputStream out = new FileOutputStream(file);
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
updateImageTable(file, index); // Implement Your own method to update ur DB table, U can access file location from DB table for future use of images
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
Convert your downloaded image into bitmap and the save to desired location in cellphone. Then You can reuse image.
private File storeImageExternalMemory(String dirName, String mediaName) {
String packageName = mContext.getPackageName();
File mediaStorageDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/Android/data/" + packageName + dirName);
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath(), mediaName + ".jpeg");
return mediaFile;
}
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
return Environment.MEDIA_MOUNTED.equals(state);
}
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
return Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state);
}
How can I download a file(image/video) from my PHP server using Retrofit2 ?
I wasn't able to find any resources or tutorials online on how to proceed; I found this post that treats a certain download error on SO but it's not very clear to me. Could anyone point me to the right direction?
UPDATE:
Here is my code:
FileDownloadService.java
public interface FileDownloadService {
#GET(Constants.UPLOADS_DIRECTORY + "/{filename}")
#Streaming
Call<ResponseBody> downloadRetrofit(#Path("filename") String fileName);
}
MainActivity.java (#Blackbelt's solution)
private void downloadFile(String filename) {
FileDownloadService service = ServiceGenerator
.createService(FileDownloadService.class, Constants.SERVER_IP_ADDRESS);
Call<ResponseBody> call = service.downloadRetrofit("db90408a4bb1ee65d3e09d261494a49f.jpg");
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(final Response<ResponseBody> response, Retrofit retrofit) {
try {
InputStream is = response.body().byteStream();
FileOutputStream fos = new FileOutputStream(
new File(Environment.getExternalStorageDirectory(), "image.jpg")
);
int read = 0;
byte[] buffer = new byte[32768];
while ((read = is.read(buffer)) > 0) {
fos.write(buffer, 0, read);
}
fos.close();
is.close();
} catch (Exception e) {
Toast.makeText(MainActivity.this, "Exception: " + e.toString(), Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Throwable t) {
Toast.makeText(MainActivity.this, "Failed to download file...", Toast.LENGTH_LONG).show();
}
});
}
I get a FileNotFoundException when USB debugging is active, & a NetworkOnMainThreadException when not.
MainActivity.java: (#Emanuel's solution)
private void downloadFile(String filename) {
FileDownloadService service = ServiceGenerator
.createService(FileDownloadService.class, Constants.SERVER_IP_ADDRESS);
Call<ResponseBody> call = service.downloadRetrofit("db90408a4bb1ee65d3e09d261494a49f.jpg");
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(final Response<ResponseBody> response, Retrofit retrofit) {
Log.i(TAG, "external storage = " + (Environment.getExternalStorageState() == null));
Toast.makeText(MainActivity.this, "Downloading file... " + Environment.getExternalStorageDirectory(), Toast.LENGTH_LONG).show();
File file = new File(Environment.getDataDirectory().toString() + "/aouf/image.jpg");
try {
file.createNewFile();
Files.asByteSink(file).write(response.body().bytes());
} catch (Exception e) {
Toast.makeText(MainActivity.this,
"Exception: " + e.toString(),
Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Throwable t) {
Toast.makeText(MainActivity.this, "Failed to download file...", Toast.LENGTH_LONG).show();
}
});
}
I get a FileNotFoundException.
This is a little example showing how to download the Retrofit JAR file. You can adapt it to your needs.
This is the interface:
import com.squareup.okhttp.ResponseBody;
import retrofit.Call;
import retrofit.http.GET;
import retrofit.http.Path;
interface RetrofitDownload {
#GET("/maven2/com/squareup/retrofit/retrofit/2.0.0-beta2/{fileName}")
Call<ResponseBody> downloadRetrofit(#Path("fileName") String fileName);
}
And this is a Java class using the interface:
import com.google.common.io.Files;
import com.squareup.okhttp.ResponseBody;
import retrofit.Call;
import retrofit.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String... args) {
Retrofit retrofit = new Retrofit.Builder().
baseUrl("http://repo1.maven.org").
build();
RetrofitDownload retrofitDownload = retrofit.create(RetrofitDownload.class);
Call<ResponseBody> call = retrofitDownload.downloadRetrofit("retrofit-2.0.0-beta2.jar");
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Response<ResponseBody> response, Retrofit retrofitParam) {
File file = new File("retrofit-2.0.0-beta2.jar");
try {
file.createNewFile();
Files.asByteSink(file).write(response.body().bytes());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable t) {
}
});
}
}
If anybody stumbles upon this response this is how i did it using retrofit in conjunction with Rx. Every downloaded file is cached, and any subsequent requests with the same url will return the already downloaded file.
In order to use this just subscribe to this observable and pass your url. This will save your file in downloads directory so make sure to ask for permissions if your app targets API 23 or greater.
public Observable<File> getFile(final String filepath) {
URL url = null;
try {
url = new URL(filepath);
} catch (MalformedURLException e) {
e.printStackTrace();
}
final String name = url.getPath().substring(url.getPath().lastIndexOf("/") + 1);
final File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), name);
if (file.exists()) {
return Observable.just(file);
} else {
return mRemoteService.getFile(filepath).flatMap(new Func1<Response<ResponseBody>, Observable<File>>() {
#Override
public Observable<File> call(final Response<ResponseBody> responseBodyResponse) {
return Observable.create(new Observable.OnSubscribe<File>() {
#Override
public void call(Subscriber<? super File> subscriber) {
try {
final File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsoluteFile(), name);
BufferedSink sink = Okio.buffer(Okio.sink(file));
sink.writeAll(responseBodyResponse.body().source());
sink.flush();
sink.close();
subscriber.onNext(file);
subscriber.onCompleted();
file.deleteOnExit();
} catch (IOException e) {
Timber.e("Save pdf failed with error %s", e.getMessage());
subscriber.onError(e);
}
}
});
}
});
}
}
Retrofit part of the call
#Streaming
#GET
Observable<retrofit2.Response<ResponseBody>> getFile(#Url String fileUrl);
to download a file, you might want the raw InputStream of the response and write is content on the sdcard. To do so, you should use ResponseBody as T for your return type, Call<ResponseBody>. You will then use Retrofit to enqueue a
Callback<ResponseBody>
and when the onResponse
#Override
public void onResponse(final Response<ResponseBody> response, Retrofit retrofit) {
is invoked, you can retrieve the InputStream, with response.byteStream(), read from it, and write what you read on the sdcard (have a look here)