gpt4 book ai didi

android - 如何使用 Retrofit 和 Kotlin 协程下载 PDF 文件?

转载 作者:行者123 更新时间:2023-12-02 12:05:56 24 4
gpt4 key购买 nike

我看到了像 How to download file in Android using Retrofit library? 这样的话题,他们使用 @Streaming和 RxJava/回调。

我有 Kotlin、协程、Retrofit 2.6.0 和 https://stackoverflow.com/a/56473934/2914140 中的查询:

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

我有一个改造客户:
retrofit = Retrofit.Builder()
.baseUrl(SERVER_URL)
.client(okHttpClient)
.build()

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

如果 token 参数正确,则查询返回 PDF 文件:
%PDF-1.4
%����
...

如果错误,它将返回带有错误描述的 JSON:
{
"success": 0,
"errors": {
"message": "..."
}
}

因此,ExportResponse 是一个包含 JSON 字段 POJO 的数据类。

我无法访问文件数据
Response response = restAdapter.apiRequest();

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

因为 ExportResponse 是一个数据类,所以 val response: ExportResponse = interactor.exportPdf(token)将返回数据,而不是 Retrofit 对象。

最佳答案

您可以更改 exportPdf 的返回类型至Call<ResponseBody>然后检查响应代码。如果可以,则将正文作为流读取。如果不是,请尝试反序列化 ExportResponse。
我猜它看起来像这样:

val response = restAdapter.apiRequest().execute()
if (response.isSuccessful) {
response.body()?.byteStream()//do something with stream
} else {
response.errorBody()?.string()//try to deserialize json from string
}

更新

这是我的测试的完整列表:
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.http.GET
import retrofit2.http.Url
import java.io.File
import java.io.InputStream

fun main() {
val queries = buildQueries()
check(queries, "http://127.0.0.1:5000/error")
check(queries, "http://127.0.0.1:5000/pdf")
}

private fun check(queries: Queries, url: String) {
val response = queries.exportPdf(HttpUrl.get(url)).execute()
if (response.isSuccessful) {
response.body()?.byteStream()?.saveToFile("${System.currentTimeMillis()}.pdf")
} else {
println(response.errorBody()?.string())
}
}

private fun InputStream.saveToFile(file: String) = use { input ->
File(file).outputStream().use { output ->
input.copyTo(output)
}
}

private fun buildRetrofit() = Retrofit.Builder()
.baseUrl("http://127.0.0.1:5000/")
.client(OkHttpClient())
.build()

private fun buildQueries() = buildRetrofit().create(Queries::class.java)

interface Queries {
@GET
fun exportPdf(@Url url: HttpUrl): Call<ResponseBody>
}

这是用 Flask 构建的简单服务器:

from flask import Flask, jsonify, send_file

app = Flask(__name__)


@app.route('/')
def hello():
return 'Hello, World!'


@app.route('/error')
def error():
response = jsonify(error=(dict(body='some error')))
response.status_code = 400
return response


@app.route('/pdf')
def pdf():
return send_file('pdf-test.pdf')

一切对我来说都很好

更新 2

看起来你必须在你的 Api 中写这个:
@FormUrlEncoded
@Streaming // You can also comment this line.
@POST("export-pdf/")
fun exportPdf(
@Field("token") token: String
): Call<ResponseBody>

关于android - 如何使用 Retrofit 和 Kotlin 协程下载 PDF 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56974908/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com