当使用Liferay下载大文件(GB)时,如何解决错误`Java堆空间' [英] How to fix an error `Java heap space` when downloading large files (GB) using Liferay

查看:166
本文介绍了当使用Liferay下载大文件(GB)时,如何解决错误`Java堆空间'的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using this code to download an existing file from the server on Liferay (6.2) into a local pc:

`

    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:在请求处理期间发生错误:Java堆空间

This code works fine only for small files. But downloading large files (cca 2GB) throws javax.portlet.PortletException: Error occurred during request processing: Java heap space.

如何修复这段代码,使其适用于较大的文件?
我想,合适的方法是使用某种缓冲区的大文件,我尝试它,但它不会工作,即使较小的文件之后。

How to fix this code so it works properly for larger files as well? I guess that the suitable approach would be to use some kind of a buffer for large files and I try it but it wouldn't work even for the smaller files afterwards.

推荐答案

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

First of all: I'm assuming you're doing this in a render method - and this is just plain wrong. Sooner or later this will break, because you don't have control over the output stream: It might already be committed and transmit data to the browser when your portlet starts to render. In render you always must generate a portlet's HTML code.

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

Instead, you should go to the resource serving phase of a portlet. With the ResourceRequest and ResourceResponse, you have a very similar support for setting mimetypes as with HttpServletResponse.

正因如此, ServletResponseUtil 确实是找错的地方。如果您使用Liferay中的任何内容,您应该查找 PortletResponseUtil 。有各种sendFile方法可以接受 byte [] ,其他方法接受流或文件。我建议尝试这些,如果他们仍然失败,看看你最终的实现。在最坏的情况下,只要不要使用任何Util方法。将内容从一个流复制到另一个流不是太糟糕。 (实际上,您不会在问题中对您的变量输入的静态类型提供任何线索:如果这是一个字节[] ,您的解决方案)

And for exactly that reason, ServletResponseUtil is indeed the wrong place to look for. If you use anything from Liferay, you should look for PortletResponseUtil. There are various sendFile methods that accept a byte[], others accept a stream or a file. I'd recommend to try these, if they still fail, look at the implementation you are ending up with. In the worst case, just don't use any of the Util methods. Copying content from one stream to another is not too bad. (Actually, you give no clue about the static type of your variable input in the question: If that's a byte[], there's your solution)

您可能想要提出Liferay的问题,如果纯流传输确实将整个文件读入内存,但是您的quickfix如果这确实是一个错误)将自动复制数据。

You might want to file an issue with Liferay, if indeed the pure stream-transfer does read the whole file into memory, but your quickfix (in case this is indeed a bug) would be to copy the data yourself.

这篇关于当使用Liferay下载大文件(GB)时,如何解决错误`Java堆空间'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆