当前位置: 首页 > 知识库问答 >
问题:

如何更高效地通过 http 下载大文件?

何和惬
2023-03-14

我正在尝试下载大文件(

val client = OkHttpClient()
val request = Request.Builder().url(urlString).build()
val response = client.newCall(request).execute()

val is = response.body().byteStream()

val input = BufferedInputStream(is)
val output = FileOutputStream(file)

val data = ByteArray(1024)
val total = 0L
val count : Int
do {
    count = input.read(data)
    total += count
    output.write(data, 0, count)
} while (count != -1)

output.flush()
output.close()
input.close()

这是因为它在不使用太多内存的情况下下载文件,但它似乎不必要地无效,因为它不断尝试写入更多数据,而不知道是否有任何新数据到达。这似乎也通过我自己的测试得到了证实,同时在资源非常有限的VM上运行它,因为它似乎使用了更多的CPU,同时下载速度低于python中的类似脚本,并且使用wget是有原因的。

我想知道是否有一种方法可以让某些东西回调,如果x字节可用,或者它是文件的末尾,那么我就可以调用回调,这样我就不必在不知道是否有任何数据的情况下不断尝试获取更多数据。

编辑:如果用okhttp是不可能的,我用别的东西没有问题,只是我习惯了超文本传输协议库。

共有2个答案

唐伟
2023-03-14

可以取消BufferedInputStream。或者,由于Oracle java中的默认缓冲区大小是8192,所以使用更大的字节数组,比如4096。

不过,最好是使用java.nio或try Files.copy:

Files.copy(is, file.toPath());

这将删除大约 12 行代码。

另一种方法是发送带有头的请求,以压缩gzip压缩接受编码:gzip,因此传输时间更短。在这里的响应中,当给出响应头内容编码:gzip时,可能在新gzip输入流(is)-中包装is。或者,如果可行,存储压缩文件,并添加一个以<code>结尾的附加值。广州<代码>我的传记。mdasmybiography.md.gz

范云
2023-03-14

从版本11开始,Java有一个内置的HttpClient,它实现了

具有非阻塞背压的异步数据流

如果您希望您的代码只在有数据需要处理时运行,这就是您所需要的。

如果您有能力升级到Java 11,您将能够使用HttpResponse.bodyHandler开箱即用地解决问题。ofFile主体处理程序。您不必自己实现任何数据传输逻辑。

Kotlin 示例

fun main(args: Array<String>) {    
    val client = HttpClient.newHttpClient()

    val request = HttpRequest.newBuilder()
            .uri(URI.create("https://www.google.com"))
            .GET()
            .build()

    println("Starting download...")
    client.send(request, HttpResponse.BodyHandlers.ofFile(Paths.get("google.html")))
    println("Done with download.")
}
 类似资料:
  • 问题内容: 是否有一种使用Go下载大文件的方法,该方法会将内容直接存储到文件中,而不是将所有内容都存储到内存中再写入文件?由于文件太大,因此在将其全部写入内存之前将其全部存储在内存中将耗尽所有内存。 问题答案: 我假设您的意思是通过http下载(为简便起见,省略了错误检查): http.Response的主体是阅读器,因此您可以使用带有阅读器的任何功能,例如一次读取一个块,而不是一次读取所有块。在

  • 问题内容: 使用PHP,我试图提供由于授权问题而不在网络可访问目录中的大文件(最大可能为200MB)。当前,我使用一个调用以及一些标头来提供文件,但是似乎PHP在发送之前先将其加载到内存中。我打算在共享托管服务器上进行部署,这将不允许我使用太多内存或添加自己的Apache模块(例如X- Sendfile)。 出于安全原因,我不能让我的文件位于可通过网络访问的目录中。有人知道我可以在共享主机服务器上

  • 本文向大家介绍如何通过PHP脚本下载大文件?,包括了如何通过PHP脚本下载大文件?的使用技巧和注意事项,需要的朋友参考一下 要通过PHP脚本下载大文件,代码如下- 示例 输出结果 这将产生以下输出- 函数“ readfile_chunked”(用户定义)具有两个参数:文件名和返回字节数的默认值“ true”,表示已成功下载大文件。声明了变量“ chunksize”,其中每个块需要读取的字节数。将'

  • 为了完整起见,获取数据的服务如下所示,但它所做的唯一事情是发出请求,并在成功时不进行映射地传递数据:

  • 本文向大家介绍如何通过表单下载文件?相关面试题,主要包含被问及如何通过表单下载文件?时的应答技巧和注意事项,需要的朋友参考一下 form 表单的action设置为接口地址,设置method为post/get : 根据需要传递的参数设置多个: 如果请求的接口不需要参数,建议设置一个input,否则可能会引起报错。 submit提交到后台

  • 问题内容: 我正在使用使用build.xml文件的ant。这是命令: Java版本:1.8.0蚂蚁版本:1.7.1 它挂在这里: 我收到连接超时错误: Ant还调用了从maven存储库中获取一些文件的方法,build.xml文件的一部分是这样的: 我将这些行放入build.xml文件中: 仍然与Maven进行蚂蚁连接,以通过http挂起获取一些jar文件。我这样做对吗?谢谢。 问题答案: 您正在混