Wie lade ich eine Datei in Android mithilfe der Retrofit-Bibliothek herunter?

Lesezeit: 7 Minuten

Benutzeravatar von Dr. Ehsan Ali
Dr. Ehsan Ali

Ich muss alle Dateitypen (Binärdateien, Bilder, Texte usw.) mithilfe der Retrofit-Bibliothek in meiner App herunterladen. Alle Beispiele im Internet verwenden die HTML-GET-Methode. Ich muss POST verwenden, um das automatische Caching zu verhindern.

Meine Frage ist, wie man eine Datei mit der POST-Methode in Retrofit herunterlädt.

  • Versuchen Sie Folgendes: stackoverflow.com/questions/32878478/…

    – Ugali weich

    17. April 2016 um 21:01 Uhr

  • Versuchen Sie das nicht 🙂 Es ist die zweite Antwort auf die Frage.

    – CoolMind

    10. Juli 2019 um 14:30 Uhr

Benutzeravatar von Suraj Vaishnav
Suraj Vaishnav

In kotlinMach das:

In Ihrer Service-Add-Methode:

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

So rufen Sie diese Methode über ViewModel auf:

viewModelScope.launch {
     val responseBody=yourServiceInstance.downloadFile(url).body()
     saveFile(responseBody,pathWhereYouWantToSaveFile)
}

So speichern Sie die Datei:

fun saveFile(body: ResponseBody?, pathWhereYouWantToSaveFile: String):String{
        if (body==null)
            return ""
        var input: InputStream? = null
        try {
            input = body.byteStream()
            //val file = File(getCacheDir(), "cacheFileAppeal.srl")
            val fos = FileOutputStream(pathWhereYouWantToSaveFile)
            fos.use { output ->
                val buffer = ByteArray(4 * 1024) // or other buffer size
                var read: Int
                while (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 ""
    }

Notiz:

  1. Stellen Sie sicher, dass Ihre refrofit Die Basis-URL des Clients und die an downloadFile übergebene URL ergeben eine gültige Datei-URL:

Basis-URL von Retrofit + Methoden-URL von downloadFile = Datei-URL

  1. Hier verwende ich zuvor das Schlüsselwort suspend downloadFile Um dies aus ViewModel aufzurufen, habe ich verwendet viewModelScope.launch {} Sie können je nach Anruferseite unterschiedliche Coroutine-Bereiche verwenden.

  2. Jetzt pathWhereYouWantToSaveFileWenn Sie eine Datei im Dateiverzeichnis des Projekts speichern möchten, können Sie Folgendes tun:

val fileName=url.substring(url.lastIndexOf("/")+1)
val pathWhereYouWantToSaveFile = myApplication.filesDir.absolutePath+fileName
  1. Wenn Sie die heruntergeladene Datei im Datei- oder Cache-Verzeichnis speichern, müssen Sie keine Erlaubnis einholen, andernfalls kennen Sie den Vorgang für die öffentliche Speicherung.

  • „Verwenden Sie JsonReader.setLenient(true), um fehlerhaftes JSON in Zeile 1, Spalte 1, Pfad $ zu akzeptieren“ -> das ist der Fehler, den ich habe

    – Mostafa Imani

    23. Mai 2022 um 5:52 Uhr

  • nach dem Hinzufügen von GsonBuilder() .setLenient() .create(); und fügen Sie es zu addConverterFactory() hinzu, wenn ein neuer Fehler auftritt, dass der Antworttext kein Argument hat

    – Mostafa Imani

    25. Mai 2022 um 4:19

Benutzeravatar von NaviRamyle
NaviRamyle

Verwenden Sie @Streaming

Asynchron

BEARBEITEN 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) {

        }
    });

Synchron

//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();
}

  • Vielen Dank für die Antwort, ich werde es versuchen und mich dann bei Ihnen melden.

    – Dr. Ehsan Ali

    1. Okt. 2015 um 2:38

  • Das ist eine Objektklasse, Sie können sie in einfach ändern Object

    – NaviRamyle

    1. Okt. 2015 um 7:17 Uhr

  • Ich erhalte die folgende Fehlermeldung: Nur Methoden mit dem Datentyp „Response“ dürfen die Annotation „@Streaming“ haben. Ich verwende den asynchronen Modus.

    – Dr. Ehsan Ali

    5. Okt. 2015 um 1:43


  • Ich habe es gelöst, indem ich POJO in die Response-Klasse geändert habe. Danke.

    – Dr. Ehsan Ali

    5. Okt. 2015 um 1:56

  • @Ehsan Sie können Response (import retrofit.client.Response;) als Modell verwenden und einen String von diesem Response-Objekt abrufen.

    – Bheatcoker

    20. April 2016 um 7:13 Uhr


So laden Sie die Datei in Retrofit 2 herunter

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) {
                    }
                });
}

  • Dieser Code lässt sich nicht einmal kompilieren. Sie können Dinge in einem nicht initialisieren Interface.

    – Bryan Bryce

    9. August 2017 um 20:38

  • hast du versucht es zu kompilieren? Bei mir funktioniert es, und so habe ich es früher auch gemacht

    – Ugali weich

    9. August 2017 um 20:56

  • Fügen Sie für IOUtils die Abhängigkeitsimplementierung „org.apache.directory.studio:org.apache.commons.io:2.4“ hinzu.

    – tendai

    12. November 2021 um 4:22

  • java.lang.RuntimeException: Aufruf von public com.squareup.okhttp.ResponseBody() ohne Argumente fehlgeschlagen. Das ist DER FEHLER

    – Mostafa Imani

    23. Mai 2022 um 8:08

Mit Kotlin ist es ein bisschen einfacher.

API-Dienst

@GET
@Streaming
fun download(@Url url: String): Call<ResponseBody>

API-Client

object ApiClient {
    private val retrofit = ...

    val service: ApiService = retrofit.create(ApiService::class.java)
}

Download-Funktion

fun download(urlString: String, target: File) {
    val response = ApiClient.service.download(urlString).execute()
    response.body()?.byteStream()?.use {
        target.parentFile?.mkdirs()
    
        FileOutputStream(target).use { targetOutputStream ->
            it.copyTo(targetOutputStream)
        }
    } ?: throw RuntimeException("failed to download: $urlString")
}

Benutzeravatar von Spark.Bao
Spark.Bao

Wenn Sie Retrofit 2.0.0 verwenden, können Sie meine Antwort unter der Frage „Retrofit zum Herunterladen der Bilddatei verwenden“ lesen.

Der entscheidende Punkt ist die Verwendung okhttp3.ReponseBody um die rohen Binärdaten zu empfangen, kein POJO.

Und Sie möchten verwenden POST Die Methode zum Abrufen der Datei ist ganz einfach, ändern Sie sie einfach @GET Zu @POSTaber es hängt davon ab, ob Ihr Server das unterstützt POST Methode!

Benutzeravatar von CoolMind
CoolMind

Sie können den folgenden Code zum Herunterladen mit Fortschritt verwenden (Kotlin).

API-Service nachrüsten

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

Stellen Sie sicher, dass Sie hinzufügen @Streaming zum Herunterladen großer Dateien

Und fügen Sie den folgenden Code in Ihre Aktivität oder Ihr Fragment ein

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.downloadFile("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)
        })
}

Unten ist die Methode 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
    }

}

Die folgende Methode dient zur Berechnung des Fortschritts

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

Ameen Maheens Benutzeravatar
Ameen Maheen

Ich habe den folgenden Code zum Herunterladen beliebiger Dateitypen mithilfe von Retrofit verwendet …

 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;
    }
}

  • Es funktioniert auf meinem Android 5.1, aber nicht auf anderen. Ich habe es in Android 6 getestet und funktioniert nicht 0

    – Rodrigo

    8. August 2017 um 15:53

1452720cookie-checkWie lade ich eine Datei in Android mithilfe der Retrofit-Bibliothek herunter?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy