Kotlin 在Ktor中,如何将InputStream流式传输到HttpClient请求';谁的身体?
我正在使用并且我有一个InputStream对象,我想用它作为我在下一行发出的HttpClient请求的主体。直到Ktor 0.95之前,有一个对象似乎就是这样做的,但它在1.0.0版本时已从Ktor中删除(不幸的是,无法找出原因) 我可以使用ByteArrayContent(见下面的代码)使其工作,但我宁愿找到一个不需要将整个InputStream加载到内存中的解决方案Kotlin 在Ktor中,如何将InputStream流式传输到HttpClient请求';谁的身体?,kotlin,ktor,ktor-client,Kotlin,Ktor,Ktor Client,我正在使用并且我有一个InputStream对象,我想用它作为我在下一行发出的HttpClient请求的主体。直到Ktor 0.95之前,有一个对象似乎就是这样做的,但它在1.0.0版本时已从Ktor中删除(不幸的是,无法找出原因) 我可以使用ByteArrayContent(见下面的代码)使其工作,但我宁愿找到一个不需要将整个InputStream加载到内存中的解决方案 ByteArrayContent(input.readAllBytes()) 这段代码是一个简单的测试用例,模拟了我试图实
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]
如果我遗漏了任何相关信息,请告诉我
谢谢 Ktor 1.2.2中唯一的API(我发现…)可能是发送一个多部分请求,这需要您的接收服务器能够处理,但它确实支持直接输入流
从他们的文档中:
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"))
}
请注意,仍然需要使用InputStreams上的大多数方法关闭inputStream
K或来源:
Kotlin Source:这是我在Ktor 1.3.0上上传文件到GCP的方法:
client.put<Unit> {
url(url)
method = HttpMethod.Put
body = ByteArrayContent(file.readBytes(), ContentType.Application.OctetStream)
}
client.put{
url(url)
方法=HttpMethod.Put
body=ByteArrayContent(file.readBytes(),ContentType.Application.OctetStream)
}
实现这一点的一种方法是创建的子类,并将其设置到post请求的正文中
一个例子如下所示:
class StreamContent(private val pdfFile:File): OutgoingContent.WriteChannelContent() {
override suspend fun writeTo(channel: ByteWriteChannel) {
val readChannel = pdfFile.inputStream().channel
var copiedBytes: Long
do {
copiedBytes = readChannel.copyTo(channel, 1024)
} while (copiedBytes > 0)
}
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)
}
class StreamContent(private val pdfFile:File):OutgoingContent.WriteChannelContent(){
覆盖暂停乐趣写入(通道:字节写入通道){
val readChannel=pdfFile.inputStream().channel
var copiedBytes:长
做{
copiedBytes=readChannel.copyTo(通道,1024)
}而(复制字节>0)
}
覆盖val contentType=contentType.Application.Pdf
重写val contentLength:Long=pdfFile.length()
}
//暂停运行
val pdfFile=File(“c:\\tmp\\foo.pdf”)
val client=HttpClient()
val结果=客户端。post(“http://upload.url") {
正文=流内容(Pdfile)
}
在内存中读取整个内容是明智的。
class StreamContent(private val pdfFile:File): OutgoingContent.WriteChannelContent() {
override suspend fun writeTo(channel: ByteWriteChannel) {
val readChannel = pdfFile.inputStream().channel
var copiedBytes: Long
do {
copiedBytes = readChannel.copyTo(channel, 1024)
} while (copiedBytes > 0)
}
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)
}