我正在使用此代码将现有文件从 Liferay (6.2) 上的服务器下载到本地电脑中:
`
File file = getFile(diskImage.getImageType(), diskImage.getId());
HttpServletRequest httpReq = PortalUtil.getHttpServletRequest(request);
HttpServletResponse httpResp = PortalUtil.getHttpServletResponse(response);
httpResp.setContentType("application/octet-stream");
httpResp.setHeader("Content-Transfer-Encoding", "binary");
httpResp.setHeader("Content-Length", String.valueOf(file.length()));
httpResp.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
try (InputStream input = new FileInputStream(file)) {
ServletResponseUtil.sendFile(httpReq, httpResp, file.getName(), input, "application/octet-stream");
} catch (Exception e) {
throw new FilesManagerException(e);
}
}
`
此代码仅适用于小文件。但是下载大文件 (cca 2GB) 会抛出 javax.portlet.PortletException: Error occurred during request processing: Java heap space
。
如何修复此代码,使其对较大的文件也能正常工作? 我想合适的方法是对大文件使用某种缓冲区,我试过了,但即使对于较小的文件,它也不起作用。
最佳答案
首先:我假设您是在渲染方法中执行此操作 - 这是完全错误的。这迟早会中断,因为您无法控制输出流:当您的 portlet 开始呈现时,它可能已经提交并向浏览器传输数据。在呈现中,您始终必须生成 portlet 的 HTML 代码。
相反,您应该转到 portlet 的资源服务阶段。使用 ResourceRequest
和 ResourceResponse
,您对设置 mimetypes 的支持与 HttpServletResponse 非常相似。
正是出于这个原因,ServletResponseUtil
确实是错误的查找位置。如果您使用 Liferay 的任何东西,您应该寻找 PortletResponseUtil
。有多种接受 byte[]
的 sendFile 方法,其他方法接受流或文件。我建议尝试这些,如果它们仍然失败,请查看您最终的实现。在最坏的情况下,不要使用任何 Util 方法。将内容从一个流复制到另一个流并不算太糟糕。 (实际上,您没有提供有关问题中变量 input
的静态类型的任何线索:如果那是一个 byte[]
,那么您的解决方案就在这里)
如果纯流传输确实将整个文件读入内存,您可能想提交 Liferay 问题,但您的快速修复(如果这确实是一个错误)将是您自己复制数据。
关于java - 使用 Liferay 下载大文件 (GB) 时如何修复错误 `Java heap space`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44269111/