我正在使用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]
让我知道是否错过任何相关信息,
谢谢!
答案 0 :(得分: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
科特琳资料来源:https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-input-stream/index.html
答案 1 :(得分:0)
这是我在Ktor 1.3.0上将文件上传到GCP的方法:
client.put<Unit> {
url(url)
method = HttpMethod.Put
body = ByteArrayContent(file.readBytes(), ContentType.Application.OctetStream)
}
答案 2 :(得分:0)
一种实现方法是创建OutgoingContent.WriteChannelContent的子类,并将其设置为发布请求的正文。
一个例子可能像这样:
final scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
key: scaffoldKey,
appBar: AppBar(
title: Text("MyApp"),
),
body: InAppWebView(
initialUrl: "https://www.google.com.pk/",
onWebViewCreated: (InAppWebViewController controller) {},
onLoadStop: (InAppWebViewController controller, String url) async {
if (url.contains("youtube")) {
// get your token from url
// Navigator.pop(scaffoldKey.currentContext); // No need of this
line
Navigator.pushReplacement(scaffoldKey.currentContext,
MaterialPageRoute(builder: (context) => DD()));
}
},
),
),
);
}