How To Download File In Android Using Retrofit Library?
Solution 1:
In kotlin
, Do this:
In your service add method:
@Streaming@GET
suspend fun downloadFile(@UrlfileUrl:String): Response<ResponseBody>
To call this method, from ViewModel:
viewModelScope.launch {
val responseBody=yourServiceInstance.downloadFile(url).body()
saveFile(responseBody,pathWhereYouWantToSaveFile)
}
To save file:
funsaveFile(body: ResponseBody?, pathWhereYouWantToSaveFile: String):String{
if (body==null)
return""var input: InputStream? = nulltry {
input = body.byteStream()
//val file = File(getCacheDir(), "cacheFileAppeal.srl")val fos = FileOutputStream(pathWhereYouWantToSaveFile)
fos.use { output ->
val buffer = ByteArray(4 * 1024) // or other buffer sizevar read: Intwhile (input.read(buffer).also { read = it } != -1) {
output.write(buffer, 0, read)
}
output.flush()
}
return pathWhereYouWantToSaveFile
}catch (e:Exception){
Log.e("saveFile",e.toString())
}
finally {
input?.close()
}
return""
}
Note:
- Make sure your
refrofit
client's base url and the url passed to downloadFile makes valid file url:
Retrofit's Base url + downloadFile's method url = File url
Here I am using suspend keyword before
downloadFile
to call this from ViewModel, I have usedviewModelScope.launch {}
you can use different coroutine scope according to your caller end.Now
pathWhereYouWantToSaveFile
, If you want to store file into project's file directory, you can do this:
val fileName=url.substring(url.lastIndexOf("/")+1)
val pathWhereYouWantToSaveFile = myApplication.filesDir.absolutePath+fileName
- If you are storing the downloaded file under file or cache directory, you don't need to acquire permission, otherwise for public storage, you know the process.
Solution 2:
Use @Streaming
Asynchronous
EDIT 1
//On your api interface@POST("path/to/your/resource")@StreamingvoidapiRequest(Callback<POJO> callback);
restAdapter.apiRequest(newCallback<POJO>() {
@Overridepublicvoidsuccess(POJO pojo, Response response) {
try {
//you can now get your file in the InputStreamInputStreamis= response.getBody().in();
} catch (IOException e) {
e.printStackTrace();
}
}
@Overridepublicvoidfailure(RetrofitError error) {
}
});
Synchronous
//On your api interface@POST("path/to/your/resource")@Streaming
Response apiRequest();
Responseresponse= restAdapter.apiRequest();
try {
//you can now get your file in the InputStreamInputStreamis= response.getBody().in();
} catch (IOException e) {
e.printStackTrace();
}
Solution 3:
This is How to DOWNLOAD file in Retrofit 2
publicinterfaceServerAPI {
@GET
Call<ResponseBody> downlload(@Url String fileUrl);
Retrofitretrofit=newRetrofit.Builder()
.baseUrl("http://192.168.43.135/retro/") // REMEMBER TO END with /
.addConverterFactory(GsonConverterFactory.create())
.build();
}
//How To Callpublicvoiddownload(){
ServerAPIapi= ServerAPI.retrofit.create(ServerAPI.class);
api.downlload("http://192.168.43.135/retro/pic.jpg").enqueue(newCallback<ResponseBody>() {
@OverridepublicvoidonResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
Filepath= Environment.getExternalStorageDirectory();
Filefile=newFile(path, "file_name.jpg");
FileOutputStreamfileOutputStream=newFileOutputStream(file);
IOUtils.write(response.body().bytes(), fileOutputStream);
}
catch (Exception ex){
}
}
@OverridepublicvoidonFailure(Call<ResponseBody> call, Throwable t) {
}
});
}
Solution 4:
If you use Retrofit 2.0.0, you can refer my answer under the question -- Use retrofit to download image file.
The key point is use okhttp3.ReponseBody
to receive the raw binary data, not any POJO.
And you want to use POST
method to get the file, it's easy, just change @GET
to @POST
, but it depend whether your server support the POST
method!
Solution 5:
You can use below code for downloading with progress (Kotlin)
Retrofit Api Service
@Streaming@GET
fun downloadFile(@UrlfileUrl: String): Observable<Response<ResponseBody>>
make sure you add @Streaming
for large file downloading
And paste below code in your Activity or Fragment
fundownloadfileFromRetrofit() {
val retrofit = Retrofit.Builder()
.baseUrl("ENTER_YOUR_BASE_URL")
.client(OkHttpClient.Builder().build())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build()
val downloadService = retrofit.create(RetrofitApi::class.java)
downloadService.downloadFile("FILE_URL_PATH").observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io()).subscribe({
val task = object : AsyncTask<Void, Integer, Void>() {
overridefundoInBackground(vararg voids: Void): Void? {
val writtenToDisk =writeResponseBodyToDisk(it.body()!!)
println("file download was a success? $writtenToDisk")
returnnull
}
}
task.execute()
}, {
print(it.message)
})
}
below is the writeResponseBodyToDisk method
funwriteResponseBodyToDisk(body: ResponseBody): Boolean {
val appDirectoryName = "YOUR_DIRECTORY_NAME"val filename = "YOUR_FILE_NAME"val apkFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), filename)
try {
var inputStream: InputStream? = nullvar outputStream: OutputStream? = nulltry {
val fileReader = ByteArray(4096)
val fileSize = body.contentLength()
var fileSizeDownloaded: Long = 0
inputStream = body.byteStream()
outputStream = FileOutputStream(apkFile)
while (true) {
val read = inputStream!!.read(fileReader)
if (read == -1) {
break
}
outputStream.write(fileReader, 0, read)
fileSizeDownloaded += read.toLong()
calulateProgress(fileSize.toDouble(),fileSizeDownloaded.toDouble()
println("file downloading $fileSizeDownloaded of $fileSize")
outputStream.flush()
returntrue
} catch (e: Exception) {
println(e.toString())
returnfalse
} finally {
if (inputStream != null) {
inputStream!!.close()
}
outputStream?.close()
}
} catch (e: Exception) {
println(e.toString())
returnfalse
}
}
below method is for calculate progress
funcalulateProgress(totalSize:Double,downloadSize:Double):Double{
return ((downloadSize/totalSize)*100)
}
Post a Comment for "How To Download File In Android Using Retrofit Library?"