web-dev-qa-db-fra.com

Comment télécharger un fichier sous Android à l'aide de la bibliothèque Retrofit?

Je dois télécharger tous les types de fichiers (binaire, image, texte, etc.) à l'aide de la bibliothèque de modifications dans mon application. Tous les exemples sur le net utilisent la méthode HTML GET. Je dois utiliser POST pour empêcher la mise en cache automatique.

Ma question est de savoir comment télécharger un fichier avec la méthode POST dans Retrofit? 

15
Ehsan

Utilisez @Streaming

Asynchrone  

EDIT 1

//On your api interface
@POST("path/to/your/resource")
@Streaming
void apiRequest(Callback<POJO> callback);

restAdapter.apiRequest(new Callback<POJO>() {
        @Override
        public void success(POJO pojo, Response response) {
            try {
                //you can now get your file in the InputStream
                InputStream is = response.getBody().in();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void failure(RetrofitError error) {

        }
    });

Synchrone

//On your api interface
@POST("path/to/your/resource")
@Streaming
Response apiRequest();

Response response = restAdapter.apiRequest();

try {
    //you can now get your file in the InputStream
    InputStream is = response.getBody().in();
} catch (IOException e) {
    e.printStackTrace();
}
9
NaviRamyle

Voici comment télécharger le fichier dans Retrofit 2

public interface ServerAPI {
        @GET
        Call<ResponseBody> downlload(@Url String fileUrl);

        Retrofit retrofit =
                new Retrofit.Builder()
                        .baseUrl("http://192.168.43.135/retro/") // REMEMBER TO END with /
                        .addConverterFactory(GsonConverterFactory.create())
                 .build();

}

    //How To Call
public void download(){
        ServerAPI api = ServerAPI.retrofit.create(ServerAPI.class);
        api.downlload("http://192.168.43.135/retro/pic.jpg").enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                        try {
                            File path = Environment.getExternalStorageDirectory();
                            File file = new File(path, "file_name.jpg");
                            FileOutputStream fileOutputStream = new FileOutputStream(file);
                            IOUtils.write(response.body().bytes(), fileOutputStream);
                        }
                        catch (Exception ex){
                        }
                    }

                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                    }
                });
}
4
ugali soft

Si vous utilisez Retrofit 2.0.0, vous pouvez consulter ma réponse sous la question - Utiliser Retrofit pour télécharger le fichier image .

Le point clé est d'utiliser okhttp3.ReponseBody pour recevoir les données binaires brutes, pas n'importe quel POJO.

Et vous voulez utiliser la méthode POST pour obtenir le fichier, c'est simple, changez simplement @GET en @POST, mais cela dépend du fait que votre serveur prenne en charge la méthode POST!

2
Spark.Bao

J'ai utilisé le code suivant pour télécharger n'importe quel type de fichier à l'aide de retrofit ...

 File file = new File("Your_File_path/name");

  private void startDownload() {

    if (!NetWorkUtils.getInstance(context).isNetworkAvailable()) {
        Toast.makeText(context, "No data connection available", Toast.LENGTH_SHORT).show();
        return;
    }

    showProgressDialog();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(FILE_BASE_URL)
            .build();

    FileHandlerService handlerService = retrofit.create(FileHandlerService.class);

    Call<ResponseBody> call = handlerService.downloadFile(mFileName);
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            dismissProgressDialog();
            if (response.isSuccessful()) {
                if (writeResponseBodyToDisk(response.body())) {
                    listener.onFileLoaded(file);
                }
            } else {
                listener.onDownloadFailed("Resource not Found");
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            dismissProgressDialog();
            listener.onDownloadFailed("Download Failed");
            t.printStackTrace();
        }
    });

}


interface FileHandlerService {

    @GET("uploads/documents/{file_name}")
    Call<ResponseBody> downloadFile(
            @Path("file_name") String imageName);
}

private boolean writeResponseBodyToDisk(ResponseBody body) {
    try {

        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            byte[] fileReader = new byte[4096];

            long fileSize = body.contentLength();
            long fileSizeDownloaded = 0;

            inputStream = body.byteStream();
            outputStream = new FileOutputStream(file);

            while (true) {
                int read = inputStream.read(fileReader);

                if (read == -1) {
                    break;
                }

                outputStream.write(fileReader, 0, read);

                fileSizeDownloaded += read;

                Log.d(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
            }

            outputStream.flush();

            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}
1
Ameen Maheen

La déclaration de demande de téléchargement de fichiers ressemble à celle donnée ci-dessous

// option 1: a resource relative to your base URL
@GET("/resource/example.Zip")
Call<ResponseBody> downloadFileWithFixedUrl();

// option 2: using a dynamic URL
@GET
Call<ResponseBody> downloadFileWithDynamicUrlSync(@Url String fileUrl);  

Après avoir déclaré votre demande, appelez comme ceci

FileDownloadService downloadService = ServiceGenerator.create(FileDownloadService.class);

Call<ResponseBody> call = downloadService.downloadFileWithDynamicUrlSync(fileUrl);

call.enqueue(new Callback<ResponseBody>() {  
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        if (response.isSuccess()) {
            Log.d(TAG, "server contacted and has file");

            boolean writeToDisk = writeToDisk(response.body());

            Log.d(TAG, "file downloaded " + writtenToDisk);
        } else {
            Log.d(TAG, "server error");
        }
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        Log.e(TAG, "error");
    }
});

Implémentez également cette méthode pour archiver votre carte SD.

private boolean writeToDisk(ResponseBody body) {  
    try { File mediaStorageDir = new File(
                Environment
                        .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                "ProfileImage");

        // Create the storage directory if it does not exist
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                Log.e("ProfileImage", "Oops! Failed create "
                        + "ProfileImage" + " directory");
            }
        }
        File futureStudioIconFile = new File(mediaStorageDir.getPath() + File.separator
                + "userImage.png");

        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            byte[] fileReader = new byte[4096];

            long fileSize = body.contentLength();
            long fileSizeDownloaded = 0;

            inputStream = body.byteStream();
            outputStream = new FileOutputStream(futureStudioIconFile);

            while (true) {
                int read = inputStream.read(fileReader);

                if (read == -1) {
                    break;
                }

                outputStream.write(fileReader, 0, read);

                fileSizeDownloaded += read;

                Log.d(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
            }

            outputStream.flush();

            return true;
        } catch (IOException e) {
            return false;
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }

            if (outputStream != null) {
                outputStream.close();
            }
        }
    } catch (IOException e) {
        return false;
    }
}
0
Prashant Sharma

Vous pouvez utiliser le code ci-dessous pour télécharger avec progress (Kotlin)

Service Api Retrofit

@Streaming
@GET
fun downloadFile(@Url fileUrl: String): Observable<Response<ResponseBody>>

assurez-vous d’ajouter @ {Streming} pour le téléchargement de fichiers volumineux.

Et collez ci-dessous le code dans votre activité ou fragment

fun downloadfileFromRetrofit() {
    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.getFile("FILE_URL_PATH").observeOn(AndroidSchedulers.mainThread())
        .subscribeOn(Schedulers.io()).subscribe({
            val task = object : AsyncTask<Void, Integer, Void>() {
                override fun doInBackground(vararg voids: Void): Void? {
                    val writtenToDisk =writeResponseBodyToDisk(it.body()!!)
                    println("file download was a success? $writtenToDisk")
                    return null
                }
            }
            task.execute()
        }, {
            print(it.message)
        })
}

ci-dessous est la méthode writeResponseBodyToDisk

fun writeResponseBodyToDisk(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? = null
        var outputStream: OutputStream? = null
        try {
            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()

            return true
        } catch (e: Exception) {
            println(e.toString())
            return false
        } finally {
            if (inputStream != null) {
                inputStream!!.close()
            }
            outputStream?.close()
        }
    } catch (e: Exception) {
        println(e.toString())
        return false
    }

}

ci-dessous la méthode est pour calculer le progrès

 fun calulateProgress(totalSize:Double,downloadSize:Double):Double{
    return ((downloadSize/totalSize)*100)
}
0
Shahid Khan

Inclure la fonction suivante dans MainActivity.Java:

void getRetrofitImage() {

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(url)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    RetrofitImageAPI service = retrofit.create(RetrofitImageAPI.class);

    Call<ResponseBody> call = service.getImageDetails();

    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Response<ResponseBody> response, Retrofit retrofit) {

            try {

                Log.d("onResponse", "Response came from server");

                boolean FileDownloaded = DownloadImage(response.body());

                Log.d("onResponse", "Image is downloaded and saved ? " + FileDownloaded);

            } catch (Exception e) {
                Log.d("onResponse", "There is an error");
                e.printStackTrace();
            }

        }

        @Override
        public void onFailure(Throwable t) {
            Log.d("onFailure", t.toString());
        }
    });
}

La partie de traitement de fichier du téléchargement d’image sera:

private boolean DownloadImage(ResponseBody body) {

    try {
        Log.d("DownloadImage", "Reading and writing file");
        InputStream in = null;
        FileOutputStream out = null;

        try {
            in = body.byteStream();
            out = new FileOutputStream(getExternalFilesDir(null) + File.separator + "AndroidTutorialPoint.jpg");
            int c;

            while ((c = in.read()) != -1) {
                out.write(c);
            }
        }
        catch (IOException e) {
            Log.d("DownloadImage",e.toString());
            return false;
        }
        finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }

        int width, height;
        ImageView image = (ImageView) findViewById(R.id.imageViewId);
        Bitmap bMap = BitmapFactory.decodeFile(getExternalFilesDir(null) + File.separator + "AndroidTutorialPoint.jpg");
        width = 2*bMap.getWidth();
        height = 6*bMap.getHeight();
        Bitmap bMap2 = Bitmap.createScaledBitmap(bMap, width, height, false);
        image.setImageBitmap(bMap2);

        return true;

    } catch (IOException e) {
        Log.d("DownloadImage",e.toString());
        return false;
    }
}

Vous pouvez le voir dans le didacticiel complet: Téléchargement d’image avec Retrofit 2.0

0
Navneet Goel