4

我正在使用Ktor 1.2.2,并且我有一个 InputStream 对象,我想将其用作我提出的 HttpClient 请求的主体。在 Ktor 0.95 之前,这个InputStreamContent对象似乎就是这样做的,但它已在 1.0.0 版本中从 Ktor 中删除(不幸的是无法弄清楚原因)。

我可以使用 ByteArrayContent 使其工作(参见下面的代码),但我宁愿找到一个不需要将整个 InputStream 加载到内存中的解决方案......

ByteArrayContent(input.readAllBytes())

这段代码是一个简单的测试用例,模拟了我想要实现的目标:

val file = File("c:\\tmp\\foo.pdf")
val inputStream = file.inputStream()
val client = HttpClient(CIO)
client.call(url) {
      method = HttpMethod.Post
      body = inputStream // TODO: Make this work :(
    }
// [... other code that uses the response below]

如果我错过了任何相关信息,请告诉我,

谢谢!

4

3 回答 3

2

实现此目的的一种方法是创建OutgoingContent.WriteChannelContent的子类,并将其设置为您的发布请求的正文。

一个示例可能如下所示:

class StreamContent(private val pdfFile:File): OutgoingContent.WriteChannelContent() {
    override suspend fun writeTo(channel: ByteWriteChannel) {
        pdfFile.inputStream().copyTo(channel, 1024)
    }
    override val contentType = ContentType.Application.Pdf
    override val contentLength: Long = pdfFile.length()
}


// in suspend function
val pdfFile = File("c:\\tmp\\foo.pdf")
val client = HttpClient()
val result = client.post<HttpResponse>("http://upload.url") {
    body = StreamContent(pdfFile)
}
于 2020-11-30T20:10:12.467 回答
1

这就是我在 Ktor 1.3.0 上将文件上传到 GCP 的方法:

client.put<Unit> {
    url(url)
    method = HttpMethod.Put
    body = ByteArrayContent(file.readBytes(), ContentType.Application.OctetStream)
}
于 2020-02-23T14:31:07.903 回答
0

Ktor 1.2.2 中唯一的 API(我发现...)可能会发送一个多部分请求,这将需要您的接收服务器能够处理此问题,但它确实支持直接 InputStream。

从他们的文档中:

val data: List<PartData> = formData {
    // Can append: String, Number, ByteArray and Input.
    append("hello", "world")
    append("number", 10)
    append("ba", byteArrayOf(1, 2, 3, 4))
    append("input", inputStream.asInput())
    // Allow to set headers to the part:
    append("hello", "world", headersOf("X-My-Header" to "MyValue"))
}

话虽这么说,我不知道它在内部是如何工作的,并且可能仍然会加载整个流的内存。

readBytes 方法是缓冲的,因此不会占用整个内存。

inputStream.readBytes()
inputStream.close()

请注意,您仍然需要使用 InputStreams 上的大多数方法关闭 inputStream

Ktor 来源:https ://ktor.io/clients/http-client/call/requests.html#the-submitform-and-submitformwithbinarydata-methods

Kotlin 源码:https ://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-input-stream/index.html

于 2019-06-21T16:47:44.067 回答