我正在尝试使用 kotlin 创建一个 android 应用程序,该应用程序需要有一个迷你下载管理器,因为我需要下载 100MB 到 8GB 的文件,当服务器支持暂停时,用户可以暂停并稍后恢复下载,搜索我发现Ktor 库并阅读文档以及 youtube 上的一些视频,我设法编写了一个基本代码,我可以在其中下载文件并停止下载并继续正常进行,当我的一个测试出现错误时,有文件的 url模式是:http://server.com/files?file=/10/55/file.zip
问题是我放了这个链接,但是 Ktor 转换成http://server.com/files?file=%2F10%2F55%2Ffile.zip
这个会在服务器上生成一个错误响应,因为我无权访问服务器来更改这个规则我需要发送正确的 url 而不编码。有谁知道如何做到这一点?防止 Ktor 在 url 参数中做一个,我在文档URL_encode
中找不到任何东西
我的代码是这样的:
ktor 客户端版本 1.6.7
fun startDownload(url: String, auth: String = "", userAgentS: String = "", fileName: String = ""){
val client = HttpClient(CIO)
val path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val file = File.createTempFile("File", "index", path)
runBlocking {
client.get<HttpStatement>(url){
headers {
append(HttpHeaders.Authorization, auth)
append(HttpHeaders.UserAgent, userAgentS)
append(HttpHeaders.Range, "bytes=${file.length()}-")
}
}
.execute { httpResponse ->
val channel: ByteReadChannel = httpResponse.receive()
while (!channel.isClosedForRead) {
val packet = channel.readRemaining(DEFAULT_BUFFER_SIZE.toLong())
while (!packet.isEmpty) {
val bytes = packet.readBytes()
file.appendBytes(bytes)
println("Received ${(file.length())} bytes from ${httpResponse.contentLength()}")
}
}
val pathF = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS + "/${fileName}")
file.renameTo(pathF)
println("A file saved to ${file.path}")
}
}
}
谁能帮我用ktor解决这个问题,如果没有解决方案,有人可以告诉我实现相同目标的另一种方法吗?需要使用 Kotlin。
更新 2022-02-17
感谢 Aleksei Tirman 的帮助,我设法解决了这个问题,非常感谢。基本代码如下所示:
fun startDownload(url: String, auth: String = "", userAgentS: String = "", fileName: String = ""){
val client = HttpClient(CIO)
val path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val file = File.createTempFile("File", "index", path)
runBlocking {
client.get<HttpStatement>(url){
url {
parameters.urlEncodingOption = UrlEncodingOption.NO_ENCODING
}
headers {
append(HttpHeaders.Authorization, auth)
append(HttpHeaders.UserAgent, userAgentS)
append(HttpHeaders.Range, "bytes=${file.length()}-")
}
}
.execute { httpResponse ->
val channel: ByteReadChannel = httpResponse.receive()
while (!channel.isClosedForRead) {
val packet = channel.readRemaining(DEFAULT_BUFFER_SIZE.toLong())
while (!packet.isEmpty) {
val bytes = packet.readBytes()
file.appendBytes(bytes)
println("Received ${(file.length())} bytes from ${httpResponse.contentLength()}")
}
}
val pathF = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS + "/${fileName}")
file.renameTo(pathF)
println("A file saved to ${file.path}")
}
}
}