如何防止Ktor Client对url参数进行编码?

How to prevent Ktor Client from encoding url parameters?

我正在尝试使用 kotlin 创建一个 android 应用程序,这个应用程序需要有一个迷你下载管理器,因为我需要下载 100MB 到 8GB 的​​文件,用户可以暂停并稍后恢复下载服务器支持暂停,搜索我找到了 Ktor 库并阅读了文档和 youtube 上的一些视频,我设法编写了一个基本代码,我可以在其中下载文件并停止下载并继续正常进行其中之一我的测试给出了错误,有些文件的 url 模式是:http://server.com/files?file=/10/55/file.zip

问题是我把这个 link,但是 Ktor 转换为 http://server.com/files?file=%2F10%2F55%2Ffile.zip 这会在服务器上生成错误响应,因为我没有访问服务器的权限来更改此规则我需要在没有编码的情况下发送正确的 url。有谁知道如何做到这一点?阻止 Ktor 在 url 参数中执行 URL_encode,我在 documentation

中找不到任何内容

我的代码是这样的:

ktor-client 版本 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}")
                    }
            }
}

您可以通过将 UrlEncodingOption.NO_ENCODING 值分配给 ParametersBuilderurlEncodingOption 属性 来禁用查询参数编码。这是一个例子:

val requestBuilder = HttpRequestBuilder()
requestBuilder.url {
    protocol = URLProtocol.HTTP
    host = "httpbin.org"
    path("get")
    parameters.urlEncodingOption = UrlEncodingOption.NO_ENCODING
    parameters.append("file", "/10/55/file.zip")
}

val response = client.get<String>(requestBuilder)