0

私はkotlinでAndroidアプリを作成しようとしています.100MBから8GBまでのファイルをダウンロードする必要があるため、このアプリにはミニダウンロードマネージャーが必要です.サーバーが一時停止をサポートしている場合、ユーザーは後でダウンロードを一時停止して再開できます. KtorライブラリとドキュメントとYouTubeのいくつかのビデオを読んで、ファイルをダウンロードしてダウンロードを停止するプロセスを作成し、私のテストの1つでエラーが発生したときに問題なく続行できるベースコードを書くことができましたパターンは次のとおりです。http://server.com/files?file=/10/55/file.zip

問題は、このリンクを配置したことですが、Ktor はhttp://server.com/files?file=%2F10%2F55%2Ffile.zipこれに変換してサーバー上でエラー応答を生成します。サーバーにアクセスしてこのルールを変更する必要がないため、エンコードせずに正しい URL を送信する必要があります。誰もこれを行う方法を知っていますか? KtorURL_encodeが URL パラメーターで a を実行できないようにします。ドキュメントには何も見つかりませんでした。

私のコードはこれです:

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 更新

アレクセイ・ティルマンの助けのおかげで、なんとか問題を解決できました。どうもありがとうございました。ベースコードは次のようになります。

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