Java 用于文件下载的OutputStream的内存使用情况

Java 用于文件下载的OutputStream的内存使用情况,java,web-applications,download,outputstream,Java,Web Applications,Download,Outputstream,所以我不确定到底发生了什么 假设我们在一个web应用程序中,用户请求下载一个动态生成的文件,该文件的大小可以是几mb,甚至可能是100 mb或更大。应用程序就是这样做的 String disposition = "attachment; fileName="myFile.txt"; response.setHeader("Content-Disposition", disposition); ServletOutputStream output = response.getOutputStrea

所以我不确定到底发生了什么

假设我们在一个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);
我说的对吗,整个文件永远不会完全在内存中?生成的任何数据都会发送给用户,然后在服务器上丢弃(假设一切顺利,没有数据包丢失)

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

String data = buffer.toString();
(文件为ASCII码)


因此,我的假设是否正确,特别是当多个用户同时下载大文件时,内存消耗将受到影响?

是的,在您的第一个代码片段中,数据直接流式传输到客户端,假设
service.exportFile(ID、writer、properties)的实现
本身从不将生成的数据保存在内存中,而是直接流式传输到Writer

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

总之,在我看来,你必须意识到两件事: -永远不要将数据与代码中的变量分离,而是直接将其写入输出流
-确保实现也不会在生成数据时将整个数据保存在内存中。第三方库提供了第二种解决方案,即写入文件。然而,创建唯一的文件名,然后读入并删除它们需要额外的麻烦。但我还是实现了它


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

是的,这是个坏主意,因此如果可以,我会避免使用缓冲区版本。最好是在获得数据时对其进行流式处理。(或者有那么多你不在乎的记忆)
service.exportFile(ids, writer, properties)