当前位置: 首页 > 面试题库 >

Java文件下载挂起

庞修贤
2023-03-14
问题内容

我有一个用于下载文件的网络界面。当请求进入时,我的glassfish服务器从Web服务流式传输文件,然后将内容写入输出流。我的代码工作正常,除非当文件大小变得很大(如200
MB以上)时,它挂起,显示0%在浏览器中下载,并且文件从未下载。

当我在while循环内移动flush()方法时,它也适用于大型文件。我不确定将flush()放入循环是否有问题。不知道这东西实际上是如何工作的。我的代码如下:

HttpURLConnection conn = (HttpURLConnection) downloadUri.toURL().openConnection();
        conn.setDoOutput(true);
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-Type", "application/pdf");
        if (conn.getResponseCode() == 200) {
            ServletOutputStream output;
            try (InputStream inputStream = conn.getInputStream()) {
                HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Length", conn.getHeaderField("Content-Length"));
                response.setHeader("Content-Disposition", "attachment; filename=\"" + abbr + ".pdf\"");
                output = response.getOutputStream();
                byte[] buffer = new byte[1024];
                int bytesRead;                    
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    output.write(buffer, 0, bytesRead);                        
                }
            }                 
            output.flush();
            output.close();

有什么想法吗?。感谢您调查此事。


问题答案:

flush()方法指示流实际将输出发送到流管道。

出于各种性能原因,各种流实现可以缓存输出,而不是立即写入底层流。

例如,将IO操作保存在磁盘上,这从性能的角度来看是很昂贵的。

刷新流没有问题,即使不是为了性能,在这种情况下,这也是您想要的:在刷新之前,流似乎一直被卡住,因此您希望它实际上将内容发送给客户端

也许您可以使用大于1024的缓冲区大小来查看更合适的缓冲区。

编辑:

循环冲洗或不循环冲洗的问题相对无关紧要。

您可以随时调用flush,因为它会调用底层OS流,无论这是否影响性能取决于情况。

例如,您可以评估200MB的RAM,其中流在其中缓冲文件比IO操作更重要(从性能角度而言)。

或者更简单地看重用户体验,即如果设法进行衡量,则看到文件实际下载比最终可能会遇到的性能问题更为重要。

如前所述,缓冲区越大,循环问题就越少。举个极端的例子,假设您的缓冲区为100兆字节,那么一个80兆字节的文件将仅获得一次刷新,无论如何它都将在请求结束时获得。

1k的缓冲区可能太小,4k更好,16k很好,这是IO调用和RAM消耗之间的权衡。

流应该自行完成其正常工作,但是,如果您看到200MB的文件已完全缓存,除非您调用flush,那么显然,该流可能正在优化性能,但带来了糟糕的用户体验,因此显然您需要在循环中使用它。



 类似资料:
  • 问题内容: 我试图建立一个Java小程序,将文件下载到客户端计算机。作为Java应用程序,此代码可以正常工作,但是当我尝试作为applet时,它什么也不做。我已经签名了.jar文件,但没有收到任何安全错误消息 代码是: 有人可以帮忙吗? 问题答案: 更改为: 理想情况下,您可以将输出放在以下任意一个中: 的 子目录 (可能基于主类的包名称-避免冲突)。 是应该使用户能够读取和创建文件的地方。 最终

  • 问题内容: 我编写了一些代码来下载我所做的网络广播的一集。它获取剧集的URL,并获取保存它的位置。但是,它最多只能下载16MB,然后自动取消。我不完全确定要增加此值需要更改什么值。是否可以,有人可以指出正确的方向吗?谢谢! 下载代码: 问题答案: 快速查看transferFrom的文档: 好。 计数的值1 << 24(来自原始问题)等于16M 我想这就是您的问题的答案:-)

  • 问题内容: 给定文件或目录的路径,如何确定该文件的安装点?例如,如果作为文件系统挂载,则给定文件名,我想知道它存储在根目录下。 这将是C ++语言,我希望避免通过调用外部命令。该代码应该健壮-不一定要防止故意的篡改,但绝对要面对嵌套的安装点,符号链接等。 我还没有找到一个简单的系统调用来执行此操作。看来我得自己写支票。这是我计划的粗略概述。 在shell命令中规范化文件名。 怎么样? 与&合作阅读

  • 每次出现此错误时`

  • 下载 <?php /** * 下载文件请求示例 */ require dirname(__DIR__) . '/vendor/autoload.php'; use Yurun\Util\HttpRequest; use Yurun\Util\YurunHttp; use Yurun\Util\YurunHttp\Handler\Swoole; $url = 'http://www.baid

  • 问题内容: 我在Windows中使用Docker Toolbox,并尝试将Windows文件夹安装在docker-compose.yml文件中,如下所示: 我的目标是将Docker Toolbox已经创建的boot2docker VM映像安装到该映像,然后从该映像加载到其中的nginx容器。 不幸的是,它不起作用。我在boot2docker映像中找到一个文件夹sss,但是它没有指定我的Window