【问题标题】:Memory usage of OutputStream for file downloadingOutputStream 用于文件下载的内存使用情况
【发布时间】:2013-07-04 07:13:42
【问题描述】:

所以我不太确定内心深处到底发生了什么。

假设我们在一个 Web 应用程序中,用户请求下载一个动态生成的文件,该文件的大小可能为几 mb,甚至可能为 100 mb 或更大。应用程序会这样做

String disposition = "attachment; fileName="myFile.txt";
response.setHeader("Content-Disposition", disposition);
ServletOutputStream output = response.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(output);
service.exportFile(ids, writer, properties);

整个文件永远不会完全在内存中,我说得对吗?例如。生成的任何数据都会发送给用户,然后在服务器上丢弃(假设一切顺利,没有丢包)?

我问这个是因为我需要更改生成文件的库(第 3 方),而新的库不使用标准 Java IO 东西可能是因为它只是一个 API,而实际的库是 C 语言。无论如何获取文档说要调用的缓冲区数据

String data = buffer.toString();

(文件是ASCII)

那么我的假设是否正确,即内存消耗会受到影响,尤其是当多个用户同时下载大文件时?

【问题讨论】:

  • 是的,这是个坏主意,所以如果可以的话,我会避免使用它。在获得数据时更好地流式传输数据。 (或者有那么多你不在乎的记忆)

标签: java web-applications download outputstream


【解决方案1】:

是的,在您的第一个代码中,sn-p 数据直接流式传输到客户端,假设 service.exportFile(ids, writer, properties) 的实现本身从不将生成的数据保存在内存中,而是真正将其直接流式传输到写入器。

使用String data = buffer.toString();,您将最终将整个数据放在堆空间中,最迟在调用buffer.toString()时,可能会更早,具体取决于具体实现。

最后,我认为您需要注意两点: - 永远不要将数据分配给您的 codem 中的变量,而是直接将其写入输出流 - 确保实现也永远不会在生成它时将整个数据保存在内存中

【讨论】:

    【解决方案2】:

    第 3 方库提供了第二种解决方案,即写入文件。但是,这需要额外的麻烦来创建唯一的文件名,然后将它们读入并在之后删除它们。但我还是实现了。

    service.exportFile(ids, writer, properties)
    

    ids 是要导出的记录的数据库标识符的集合,因此ids.size() 给出了结果文件大小的粗略估计。因此,只要它很小,我就使用缓冲区版本,如果文件很大,我就使用一个。

    【讨论】:

      猜你喜欢
      • 2021-08-08
      • 1970-01-01
      • 2017-09-03
      • 1970-01-01
      • 2011-09-05
      • 2010-11-17
      • 1970-01-01
      • 2020-03-07
      • 2019-08-10
      相关资源
      最近更新 更多