如何修复使用Liferay下载大文件(GB)时出现的错误“Java堆空间”

如何修复使用Liferay下载大文件(GB)时出现的错误“Java堆空间”,java,download,liferay,httprequest,Java,Download,Liferay,Httprequest,我正在使用此代码将现有文件从Liferay(6.2)上的服务器下载到本地pc: ` ` 此代码仅适用于小文件。但是下载大文件(cca 2GB)会抛出javax.portlet.portleteException:请求处理期间发生错误:Java堆空间 如何修复此代码,使其也能在较大的文件中正常工作? 我想合适的方法是为大文件使用某种缓冲区,我尝试了一下,但之后即使对较小的文件也不起作用 ServletResponseUtil.sendFile(httpReq,httpResp,file.getNa

我正在使用此代码将现有文件从Liferay(6.2)上的服务器下载到本地pc:

`

`

此代码仅适用于小文件。但是下载大文件(cca 2GB)会抛出
javax.portlet.portleteException:请求处理期间发生错误:Java堆空间

如何修复此代码,使其也能在较大的文件中正常工作? 我想合适的方法是为大文件使用某种缓冲区,我尝试了一下,但之后即使对较小的文件也不起作用

ServletResponseUtil.sendFile(httpReq,httpResp,file.getName(),输入,“应用程序/八位字节流”);这是什么

不要一次读取一个文件。使用缓冲区

response.reset();
response.setContentType("application/x-download");
response.addHeader("Content-Disposition","attachment;filename="+new String(filename.getBytes(),"utf-8"));
response.addHeader("Content-Length",""+file.length());
OutputStream toClient=new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
byte[] buffer=new byte[1024*1024*4];
int i=-1;
while((i=fis.read(buffer))!=-1){
  toClient.write(buffer,0,i);
}
fis.close();
toClient.flush();
toClient.close();
ServletResponseUtil.sendFile(httpReq,httpResp,file.getName(),输入,“应用程序/八位字节流”);这是什么

不要一次读取一个文件。使用缓冲区

response.reset();
response.setContentType("application/x-download");
response.addHeader("Content-Disposition","attachment;filename="+new String(filename.getBytes(),"utf-8"));
response.addHeader("Content-Length",""+file.length());
OutputStream toClient=new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
byte[] buffer=new byte[1024*1024*4];
int i=-1;
while((i=fis.read(buffer))!=-1){
  toClient.write(buffer,0,i);
}
fis.close();
toClient.flush();
toClient.close();

首先:我假设你是在一个渲染方法中做这件事的——这完全是错误的。这迟早会中断,因为您无法控制输出流:当portlet开始呈现时,它可能已经提交并将数据传输到浏览器。在呈现中,您必须始终生成portlet的HTML代码

相反,您应该转到portlet的资源服务阶段。使用
ResourceRequest
ResourceResponse
,您对设置mimetypes的支持与HttpServletResponse非常相似

正是出于这个原因,
ServletResponseUtil
确实是一个错误的地方。如果您使用Liferay中的任何内容,您应该查找
PortletResponseUtil
。有多种sendFile方法接受
字节[]
,其他方法接受流或文件。我建议尝试这些方法,如果仍然失败,请查看最终的实现。在最坏的情况下,不要使用任何Util方法。将内容从一个流复制到另一个流并不太糟糕。(实际上,在问题中,您没有给出关于变量
输入的静态类型的任何线索:如果这是
字节[]
,那么这就是您的解决方案)


如果纯流传输确实将整个文件读取到内存中,那么您可能希望向Liferay提交一个问题,但是您的快速修复(如果这确实是一个bug)将是自己复制数据

首先:我假设您是在渲染方法中执行此操作的,这完全是错误的。这迟早会中断,因为您无法控制输出流:当portlet开始呈现时,它可能已经提交并将数据传输到浏览器。在呈现中,您必须始终生成portlet的HTML代码

相反,您应该转到portlet的资源服务阶段。使用
ResourceRequest
ResourceResponse
,您对设置mimetypes的支持与HttpServletResponse非常相似

正是出于这个原因,
ServletResponseUtil
确实是一个错误的地方。如果您使用Liferay中的任何内容,您应该查找
PortletResponseUtil
。有多种sendFile方法接受
字节[]
,其他方法接受流或文件。我建议尝试这些方法,如果仍然失败,请查看最终的实现。在最坏的情况下,不要使用任何Util方法。将内容从一个流复制到另一个流并不太糟糕。(实际上,在问题中,您没有给出关于变量
输入的静态类型的任何线索:如果这是
字节[]
,那么这就是您的解决方案)


如果纯流传输确实将整个文件读取到内存中,那么您可能希望向Liferay提交一个问题,但是您的快速修复(如果这确实是一个bug)将是自己复制数据

谢谢您的思考,最后我使用了
PortletResponseUtil.sendFile(…)
方法,并将
.jsp
文件中的
actionURL
更改为
responseURL
。因此,我使用上述方法实现了
serversource()
。看来一切都很顺利

谢谢您的思考,最后我使用了
PortletResponseUtil.sendFile(…)
方法,并将
.jsp
文件中的
actionURL
更改为
responseURL
。因此,我使用上述方法实现了
serversource()
。看来一切都很顺利

使用命令行选项-Xmx运行Java,该选项设置堆的最大大小。是否可以使用某种实现来代替此设置?堆大小更改是否有任何负面影响?因为我不知道如何在远程Liferay服务器上使用它。我只是创建了部署在服务器上的
.war
文件。使用命令行选项-Xmx运行Java,该选项设置堆的最大大小。是否可以使用某种实现而不是此设置来实现?堆大小更改是否有任何负面影响?因为我不知道如何在远程Liferay服务器上使用它。我只是创建部署在服务器上的
.war
文件。不。我的意思是我不使用ServletResponseUtil。不。我的意思是我不使用ServletResponseUtil。