当前位置: 首页 > 知识库问答 >
问题:

使用InpuStream下载大文件

淳于玺
2023-03-14

我们有一个运行在Linux上的Weblogic服务器,有多个受管服务器。我所关心的托管服务器的最大堆大小为1024MB。该服务器上部署了多个应用程序。其中一个应用程序处理来自REST api的响应来下载250MB的文件。对于大于50 MB的文件,有时没有问题,但有时服务器会因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();
        }
    } 

由于存在内存问题,我尝试采用InpuStream方法。以下是更改后的代码:

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上运行。我使用InpuStream来解决OOM的方法可以吗?该服务没有以块的形式发送响应。我还可以采取其他方法吗?我担心我只是为了50MB的文件而遇到错误(并不总是如此)。服务器是远程服务器,由另一个组处理。我如何检查是否有其他原因导致服务器崩溃?

共有2个答案

唐景山
2023-03-14

我使用Base64InputStream来解码InputStream响应,它工作得很好。

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

然后,使用 bis 写入文件。此方法现在打印 count 变量大约在 65000。

江光明
2023-03-14

嗨,试试这个本指南。https://www.baeldung.com/java-download-file

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

祝你好运!:-)

 类似资料:
  • 问题内容: 我需要使用curl下载远程文件。 这是我的示例代码: 但是它不能处理大文件,因为它首先读取内存。 是否可以将文件直接流式传输到磁盘? 问题答案:

  • 我有一个文件表示为块的列表,目标是下载所有块,加入并保存为一个文件。 它应该适用于大文件 应该是跨浏览器解决方案 null null null null 但我仍然无法实现我的目标与涵盖的需求… 如果有人有经验,最好的解决方案,我恳请分享它在这里。谢谢

  • 问题内容: 请求是一个非常不错的库。我想用它来下载大文件。问题是不可能将整个文件保留在内存中,我需要分块读取它。这是以下代码的问题 由于某种原因,它无法按这种方式工作。仍将响应加载到内存中,然后再将其保存到文件中。 更新 如果你需要一个小型客户端,可以从FTP下载大文件,则可以在此处找到它。它支持多线程和重新连接(它确实监视连接),还可以为下载任务调整套接字参数。 问题答案: 使用以下流代码,无论

  • 问题内容: 我正在尝试创建一个文件下载程序作为后台服务,但是当计划了一个大文件时,首先将其放入内存中,然后在下载结束时将文件写入磁盘。 考虑到我可能同时下载许多文件,如何使文件逐渐写入磁盘保留内存? 这是我使用的代码: 问题答案: 我将回调更改为: 这工作得很好。

  • 问题内容: 是否有一种使用Go下载大文件的方法,该方法会将内容直接存储到文件中,而不是将所有内容都存储到内存中再写入文件?由于文件太大,因此在将其全部写入内存之前将其全部存储在内存中将耗尽所有内存。 问题答案: 我假设您的意思是通过http下载(为简便起见,省略了错误检查): http.Response的主体是阅读器,因此您可以使用带有阅读器的任何功能,例如一次读取一个块,而不是一次读取所有块。在

  • 问题内容: 我已经在我的项目中实现了角度文件保护程序,目的是下载文件,它对于小文件也可以正常工作,但是对于大于50mb的文件,我会看到下一个错误,并且在35-50mb之后会停止下载。 我试图调查互联网上的这个问题,发现下载限制为500mb,因为显然不能在RAM中存储这么多的信息。不幸的是,我没有找到其他任何可以解决该问题的解释,然后我问了后端人员,我得到的答案是,一切都很好。 那我的问题在哪里呢?