私は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}")
}
}
}