Java 使用InputStream下载大型文件

Java 使用InputStream下载大型文件,java,rest,jersey,base64,inputstream,Java,Rest,Jersey,Base64,Inputstream,我们有一个运行在Linux上的Weblogic服务器,它有多个托管服务器。我关心的托管服务器的最大堆大小为1024MB。此服务器上部署了多个应用程序。其中一个应用程序处理RESTAPI的响应,以下载250MB大小的文件。对于大于50MB的文件,有时没有问题,但有时服务器会因OOM错误而崩溃。 以下是我的代码: Client client = Client.create(); WebResource webResource = client.resource(url.toStr

我们有一个运行在Linux上的Weblogic服务器,它有多个托管服务器。我关心的托管服务器的最大堆大小为1024MB。此服务器上部署了多个应用程序。其中一个应用程序处理RESTAPI的响应,以下载250MB大小的文件。对于大于50MB的文件,有时没有问题,但有时服务器会因OOM错误而崩溃。 以下是我的代码:

Client client = Client.create();          
WebResource webResource = client.resource(url.toString());
ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);
if (response.getStatus() != 200) {
            throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
        }
String output = response.getEntity(String.class);
byte[] fileContent = Base64.decodeBase64(output.getBytes());
if (fileContent != null) {
        OutputStream out = null;
        try {
            res.reset();
            out = res.getOutputStream();
            res.setContentType(contentType);
            res.setHeader("Content-Disposition", "inline; filename=" + fileName + "; size=" + String.valueOf(fileContent.length));
            res.setContentLength(fileContent.length);
            out.write(fileContent);
        } catch (Exception ex) {
            e.printStackTrace();
        } finally {
            out.flush();
            out.close();
        }
    } 
由于内存问题,我尝试采用InputStream方法。以下是更改后的代码:

Client client = Client.create();          
WebResource webResource = client.resource(url.toString());
ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);
if (response.getStatus() != 200) {
        throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
    }
InputStream source = response.getEntityInputStream(); // IS THIS OKAY?

if (source!= null) {
        OutputStream out = null;
        int count = 0;
        try {
            byte[] buffer = new byte[1024];
            int read = 0;
            res.reset();
            res.setContentType(contentType);
            res.setHeader("Content-Disposition", "inline; filename=" + fileName);
            out = res.getOutputStream();
            while ((read = source.read(buffer)) != -1) {
                out.write(buffer, 0, read);
                count++;
            }                
            System.out.println("COUNT: " + count);// For a 60MB file, this prints 86000. why?
        } catch (Exception ex) {
            e.printStackTrace();
        }finally{
            out.flush();
            out.close();
            source.close();
        }
此代码未运行到OOM中,但文件加载失败/已损坏。问题是否与以下事实有关:它是一个Base64编码的响应,而我没有正确处理它?如果是,我该怎么办?该应用程序在Java7上运行。 我使用InputStream处理OOM的方法可以吗?该服务未分块发送响应。我还可以采取什么其他方式?我担心仅仅是50MB的文件就可能会出错(并非总是如此)。
该服务器是远程服务器,由另一个组处理。如何检查服务器崩溃是否有其他原因?

您好,请尝试本指南

这是一个很棒的站点,提供了几乎所有可以想象的场景的许多Java指南


祝你好运!:-)

我使用Base64InputStream对InputStream响应进行解码,效果很好

InputStream stream = response.getEntityInputStream();
Base64InputStream bis = new Base64InputStream(stream);

然后,使用bis编写文件。这种方法现在打印65000左右的计数变量。

是否尝试监视内存?您可以在本地开发机器上使用。它是在第一次请求时发生的吗?您确定该文件有60 MB吗?看起来更像83.9 MB。谢谢,我试试visualvm。我必须通过一些教程来学习如何从本地机器连接到远程服务器以监控内存使用情况。它不会在第一次请求时发生。文件被多次下载,没有任何问题。我确信这个文件是60MB。这就是为什么我的问题是为什么循环会进行86000次?谢谢!我已经浏览了这个链接。我相信我的问题是,当我想使用inputstream时,我没有正确处理base64编码的响应。