gpt4 book ai didi

file - Ktor - 无内存泄漏处理大文件操作

转载 作者:行者123 更新时间:2023-12-04 08:29:25 28 4
gpt4 key购买 nike

我是后端开发的新手。基本上,我想创建一个强大而简单的应用程序,它将在参数中接受一个 zip 文件 URL,然后从 URL 下载 zip 文件,最后解压缩 zip 并返回其中的 bin 文件。注意:zip 文件的大小范围为 5MB 到 150MB。我已尝试按以下方式执行所描述的操作。

package la.sample

import io.ktor.application.Application
import io.ktor.application.call
import io.ktor.client.HttpClient
import io.ktor.client.request.get
import io.ktor.http.HttpStatusCode
import io.ktor.response.respond
import io.ktor.response.respondFile
import io.ktor.routing.get
import io.ktor.routing.routing
import java.io.*


fun Application.startServer() {
routing {
get("/get-bin") {

//Gets the AWS Url from params
val awsUrl = call.request.queryParameters.get("url") ?: "Error"

// Download the zip file from the AWS URL
val client = HttpClient()
val bytes = client.get<ByteArray>(awsUrl)

//Create a temp file on the server & write the zip file bytes into it.
val file = File(".", "data.zip")
file.writeBytes(bytes)

//Call a method to unzip the file
unzipAndReturnBinFile()?.let {
call.respondFile(it) //respond with bin file
} ?: kotlin.run{
call.respond(HttpStatusCode.InternalServerError)
}
}
}
}


fun unzipAndReturnBinFile(): File? {

var exitVal = 0

//Command shell to unzip the file
Runtime.getRuntime().exec("unzip bundle.zip -d data").let {//command shell to unzip the zip file
exitVal += it.waitFor()
}

//Check if the command executed successfully
if (exitVal == 0) {

var binFile: File? = null

//check if the extracted files contain `bin`
File("data").listFiles().forEach {

if (it.name.contains(".bin")) {
binFile = it
}
}

//return bin or null otherwise
return binFile
} else {
throw Exception("Command Shell Execution failed.")
}
}

以上代码在本地机器上运行良好,与 Zip 文件大小无关。但是,当它部署到 AWS 时,如果 zip 或 bin 文件大于 100 MB,代码就会中断并给出 java.lang.OutOfMemoryError 错误。如果有人可以向我建议一种在后端处理大文件操作并能够处理 100 多个此类并发调用的正确方法,我将非常感激。谢谢。

我的远程机器的 Java 堆大小约为 1 GB。 enter image description here

最佳答案

您的问题不是来自解压缩过程

runtime exec 命令在不同的进程上运行,并且仅在 fork 进程的堆上使用最小大小来保存返回地址的指令。

导致outOfMemory的问题就在这几行

val bytes = client.get<ByteArray>(awsUrl)
val file = File(".", "data.zip")
file.writeBytes(bytes)

只需 6 个大小为 150Mb 的并发请求即可完成所有堆大小。

与其等待文件完全下载再将其保存到磁盘,不如使用 Stream,然后每次下载一大块数据时将其保存到磁盘,然后以这种方式下载文件的完整大小永远不会同时在 RAM 中。

使用 Apache commons-io ,例如:

FileUtils.copyURLToFile(URL, File)

或者,如果您想更好地控制程序,请尝试使用 Ben Noland answer

https://stackoverflow.com/a/921408/4267015

关于file - Ktor - 无内存泄漏处理大文件操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65102592/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com