Java j2ee下载文件问题,如果在后端使用相同的文件?

Java j2ee下载文件问题,如果在后端使用相同的文件?,java,jakarta-ee,download,Java,Jakarta Ee,Download,Webapp在我的项目中提供基于最终用户搜索的下载CSV文件功能,正在执行以下操作: 未使用file.createTempFileString前缀打开文件download.csv, 字符串后缀,文件目录;但始终只需下载.csv,将Sql记录集中的数据行写入其中,然后使用FileUtils将该文件的内容复制到servlet的OutputStream 记录集基于搜索条件,如1月1日至3月30日 这是否会导致一种潜在的情况,即文件中有两个用户的内容,他们使用不同的日期范围/其他筛选器并同时提交,因此J

Webapp在我的项目中提供基于最终用户搜索的下载CSV文件功能,正在执行以下操作:

未使用file.createTempFileString前缀打开文件download.csv, 字符串后缀,文件目录;但始终只需下载.csv,将Sql记录集中的数据行写入其中,然后使用FileUtils将该文件的内容复制到servlet的OutputStream

记录集基于搜索条件,如1月1日至3月30日

这是否会导致一种潜在的情况,即文件中有两个用户的内容,他们使用不同的日期范围/其他筛选器并同时提交,因此JVM会同时处理请求

现在我们在开发中,数据很少

我知道我们可以编写自动化测试来测试这一点,但我想知道理论

我建议使用Http响应的OutputStream将其作为普通的OutputSteam传递到服务层,并直接写入该层,或者封装在缓冲写入器中,然后写入它

唯一的缺点是数据写入速度比文件副本慢。 就好像记录集中有更多的数据一样,遍历它需要时间。但是请求的总时间应该更少?由于写入文件输出流的时间将与从文件复制到servlet输出流的时间相同


有人做过这方面的测试,并有测试用例或解决方案可供分享吗?

如果你真的想深入了解这两个部分,这是一个棘手的问题

并发性

当你写这个同名的东西时,如果你在一个多线程系统上工作,那么现在几乎所有的系统都是这样。我见过一些这样的编码,它会引起很多麻烦。结果文件不仅可以包含两个搜索中的行,还可以包含合并的字符

示例:

产出可能以上述方式变化:

第1例:

第2例:

我肯定会使用至少唯一的UUID.randomUUID名称来热修复这个问题

并发性

如果深入研究,使用磁盘IO是一件棘手的事情。SPEAD可能在不同的范围内变化。在JVM中,还可以有阻塞IO和非阻塞IO。阻塞一个可以等到数据真的在磁盘上,另一个会在以后刷新文件。有一本很好的读本


TL.DR:根据经验,如果内存中有合适的东西,而不必担心磁盘的问题,那么内存中最好有这些东西。如果您也使用线程内存来实现这一目的,那么也可以避免并发问题。因此,在您的情况下,最好重写给定部分以仅利用内存并写入输出。

为什么您说直接将文件写入输出流比在文件系统中创建文件以稍后通过线路发送要慢???@carlitos方式哦,我的意思是与从文件复制到Servelet输出流相比。也就是说,如果recorset有许多记录,那么迭代将需要时间,我认为这不会有什么不同,但是,对于完整的请求,写入Servlet输出流将花费更少的时间。如果不需要,我不会将请求中的数据放入文件中。更好的是,如果可以的话,应该遍历数据集并立即写入输出流。这将使客户端立即收到他的响应并开始下载数据。但是如果你真的需要这个文件,那么我会制作一个带有部分随机生成名称的文件,比如UUID,这样每个用户都可以拥有自己的文件,你就不会再有问题了。但首先,做一个单元测试,显示当前情况失败,然后修复它并显示它不再失败。@Wietrol好的,我知道如果使用UUID,更安全的方法是使用File.createTempFileString前缀、字符串后缀、文件目录;这就是你说的。但是我想知道另一种方式的优点和任何测试结果-直接到Servlet输出流直接链接到输出流的优点主要是,在传输过程中,您不需要任何硬盘存储,您的代码很可能更清楚它的功能,并且您的服务响应更快。我没有任何测试结果,但是如果你查询大量数据,你可以很容易地注意到这些差异。这是一个很好的答案。我真的希望得到一些明确的证明数据/测试案例。但是你可以得到赏金。谢谢
Thread 1 wants to write: 123456789\n
Thread 2 wants to write: abcdefghi\n
123456789
abcdefghi
1234abcd56789
efghi