如何从在 KMM 中返回可流式 pdf 文件的 api 下载文件

How to download file from an api which returns streamable pdf file in KMM

提问人:Aju 提问时间:11/16/2023 更新时间:11/16/2023 访问量:24

问:

我有一个用于 Android 和 iOS 项目的库,并且正在使用框架。我有一个 api,它返回一个可流式传输的 pdf 文件。我想编写一个应该返回平台支持的格式的 api 调用。从移动平台,我应该能够在 KMM 库中调用此 api,并使用 api 响应标头中给出的相同文件名将文件保存到移动设备中。下面是响应标头:Kotlin Multiplatform MobileKtor-client

connection: keep-alive 
 content-disposition: attachment; filename="bill_123.pdf" 
 content-length: 13161 
 content-security-policy: default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests 
 content-type: application/pdf 

当我在 Postman 中尝试此操作时,我会得到文件本身。

由于我是 KMM 的新手,因此需要帮助调用这种 api。

kotlin kotlin-multiplatform ktor ktor-client

评论


答:

1赞 Aleksei Tirman 11/16/2023 #1

如果 PDF 文件的大小适合内存,则可以将响应正文读取为 .若要获取原始文件名,请使用以下方法:ByteArrayContentDisposition.parse

val client = HttpClient {}

val response = client.get("http://localhost:8080/pdf")
val disposition = ContentDisposition.parse(response.headers[HttpHeaders.ContentDisposition] ?: "")
val filename = disposition.parameter("filename")
val bytes = response.body<ByteArray>()

此外,您可以获取正文以块形式读取文件:ByteReadChannel

val channel = client.get("http://localhost:8080/pdf").bodyAsChannel()

评论

0赞 Aju 11/16/2023
谢谢你的回答。我只是对第二个选项感到困惑,如何使第二个选项适用于 Android 和 iOS,因为在 bodyAsChannel 中需要文件,这在 iOS 上不起作用。
1赞 Aleksei Tirman 11/16/2023
您需要编写适配器来读取这两个平台的本机文件。 并且对于这两个平台都是通用的。ByteReadChannelByteReadChannelByteArray