web-dev-qa-db-fra.com

Comment télécharger PDF fichier avec modernisation et kotlin coroutines?

J'ai vu des sujets comme Comment télécharger le fichier dans Android à l'aide de la bibliothèque de rénovation? , ils utilisent @Streaming Et rxjava/rappels.

J'ai la kotlin, les coroutines, la modernisation 2.6.0 et les requêtes comme dans https://stackoverflow.com/a/56473934/291414 :

@FormUrlEncoded
@Streaming
@POST("export-pdf/")
suspend fun exportPdf(
    @Field("token") token: String
): ExportResponse

J'ai un client de modernisation:

retrofit = Retrofit.Builder()
    .baseUrl(SERVER_URL)
    .client(okHttpClient)
    .build()

service = retrofit.create(Api::class.Java)

Si un paramètre de jeton a raison, la requête renvoie PDF Fichier:

%PDF-1.4
%����
...

Si c'est faux, il retournera JSON avec une description d'erreur:

{
    "success": 0,
    "errors": {
        "message": "..."
    }
}

Donc, ExporTresponse est une classe de données contenant des champs JSON, POJO.

Je ne peux pas accéder aux données de fichier avec

Response response = restAdapter.apiRequest();

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

étant donné que ExporTreSponse est une classe de données, donc val response: ExportResponse = interactor.exportPdf(token) Retournera les données, pas d'objet à modernisation.

4
CoolMind

Merci à @andreitanana j'ai trouvé une erreur. Un problème était dans suspend dans la définition de la demande. Toutes les autres demandes conservent leur modificateur suspend, mais cette demande l'a supprimé. J'ai changé le code afin.

interface Api {
    @FormUrlEncoded
    @Streaming
    @POST("export-pdf/")
    fun exportPdf(
        @Field("token") token: String
    ): Call<ResponseBody>

    // Any another request. Note 'suspend' here.
    @FormUrlEncoded
    @POST("reject/")
    suspend fun reject(): RejectResponse
}

Ensuite, dans sa mise en œuvre, APIIMPL:

class ApiImpl : Api {

    private val retrofit by lazy { ApiClient.getRetrofit().create(Api::class.Java) }

    override fun exportPdf(
        token: String
    ): Call<ResponseBody> =
        retrofit.exportPdf(token)

    override suspend fun reject(): RejectResponse =
        // Here can be another instance of Retrofit.
        retrofit.reject()
}

CLIENT DE REDOFIT:

class ApiClient {

    companion object {

        private val retrofit: Retrofit


        init {

            val okHttpClient = OkHttpClient().newBuilder()
                .connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .build()

            val gson = GsonBuilder().setLenient().create()

            retrofit = Retrofit.Builder()
                .baseUrl(SERVER_URL)
                .client(okHttpClient)
                // .addConverterFactory(GsonConverterFactory.create(gson)) - you can add this line, I think.
                .build()
        }

        fun getRetrofit(): Retrofit = retrofit
}

Interactor:

interface Interactor {
    // Note 'suspend' here. This is for coroutine chain.
    suspend fun exportPdf(
        token: String
    ): Call<ResponseBody>
}

class InteractorImpl(private val api: Api) : Interactor {
    override suspend fun exportPdf(
        token: String
    ): Call<ResponseBody> =
        api.exportPdf(token)
}

Puis en fragment:

private fun exportPdf(view: View, token: String) {
    showProgress(view)
    launch(Dispatchers.IO) {
        try {
            val response = interactor.exportPdf(token).execute()
            var error: String? = null
            if (response.headers().get("Content-Type")?.contains(
                    "application/json") == true) {
                // Received JSON with an error.
                val json: String? = response.body()?.string()
                error = json?.let {
                    val export = ApiClient.getGson().fromJson(json,
                        ExportPdfResponse::class.Java)
                    export.errors?.common?.firstOrNull()
                } ?: getString(R.string.request_error)
            } else {
                // Received PDF.
                val buffer = response.body()?.byteStream()
                if (buffer != null) {
                    val file = context?.let { createFile(it, "pdf") }
                    if (file != null) {
                        copyStreamToFile(buffer, file)
                        launch(Dispatchers.Main) {
                            if (isAdded) {
                                hideProgress(view)
                            }
                        }
                    }
                }
            }
            if (error != null) {
                launch(Dispatchers.Main) {
                    if (isAdded) {
                        hideProgress(view)
                        showErrorDialog(error)
                    }
                }
            }
        } catch (e: Exception) {
            launch(Dispatchers.Main) {
                if (isAdded) {
                    showErrorDialog(getString(R.string.connection_timeout))
                    hideProgress(view)
                }
            }
        }
    }
}
1
CoolMind