0

我正在尝试使用 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}")
                    }
            }
}
4

1 回答 1

0

您可以通过将UrlEncodingOption.NO_ENCODING值分配urlEncodingOptionParametersBuilder. 这是一个例子:

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)
于 2022-02-16T06:58:06.620 回答