我正在开发一个Spring MVC应用程序,用户可以在其中下载文件。用户可以点击触发下载机制的附件。Spring,Java:流式文件下载以避免内存不足错误

昨天,当该多个下载和两个具有约2 GB的文件,就引起一个内存不足错误(下面登录)。

为了避免这个问题,解决这个问题的一种方法似乎是在块流下载数据,并且只处理这些块在服务层,而不是整个文件。

不幸的是,我不知道如何继续前进,任何帮助都会很好。如果这个选项不能飞,关于如何解决这个问题的任何建议。

错误日志:

HTTP Status 500 - Handler processing failed; nested exception is java.lang.OutOfMemoryError: Direct buffer memory

type Exception report

message Handler processing failed; nested exception is java.lang.OutOfMemoryError: Direct buffer memory

description The server encountered an internal error that prevented it from fulfilling this request.

exception

org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.OutOfMemoryError: Direct buffer memory

org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1303)

org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:977)

org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)

org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)

org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)

javax.servlet.http.HttpServlet.service(HttpServlet.java:620)

org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)

控制器代码:

@RequestMapping(value = "/download/attachment/{attachid}", method = RequestMethod.GET)

public void getAttachmentFromDatabase(@PathVariable("attachid") int attachid,

, HttpServletResponse response,) {

response.setContentType("application/octet-stream");

GroupAttachments groupAttachments = this.groupAttachmentsService.getAttachmenById(attachid);

response.setHeader("Content-Disposition", "attachment; filename=\"" + groupAttachments.getFileName() + "\"");

response.setContentLength(groupAttachments.getSendAttachment().length);

FileCopyUtils.copy(groupAttachments.getSendAttachment(), response.getOutputStream());

response.flushBuffer();

}

服务层:

@Override

public GroupAttachments getAttachmenById(int attachId) {

Person person = this.personService.getCurrentlyAuthenticatedUser();

GroupAttachments groupAttachments = this.groupAttachmentsDAO.getAttachmenById(attachId);

GroupMembers groupMembers = this.groupMembersService.returnMembersMatchingUsernameAccountId(person.getUsername(),

groupAttachments.getGroupId());

if (!(groupMembers == null)) {

if (person.getUsername().equals(groupMembers.getMemberUsername())) {

try {

Path path = Paths.get(msg + groupAttachments.getGroupId() + "/" +

groupAttachments.getFileIdentifier());

groupAttachments.setSendAttachment(Files.readAllBytes(path));

return groupAttachments;

} catch (IOException ignored) {

this.groupAttachmentsDAO.removeAttachment(attachId);

return null;

}

}

return null;

} else {

return null;

}

}

谢谢。 :-)

更新

新的下载机制:

控制器:

public ResponseEntity getAttachmentFromDatabase(@PathVariable("attachid") int attachid,

@PathVariable("groupaccountid") Long groupAccountId, @PathVariable("api") String api,

HttpServletResponse response,

@PathVariable("type") boolean type) {

Path path = this.groupAttachmentsService.getAttachmentPathById(attachid);

GroupAttachments groupAttachments = this.groupAttachmentsService.getAttachmentObjectOnlyById(attachid);

response.setContentType("application/octet-stream");

response.setHeader("Content-Disposition", "attachment; filename=\""+groupAttachments.getFileName()+"\"");

try {

OutputStream outputStream = response.getOutputStream();

Files.copy(path,outputStream);

outputStream.flush();

outputStream.close();

response.flushBuffer();

}

服务层:

@Override

public Path getAttachmentPathById(int attachId){

Person person = this.personService.getCurrentlyAuthenticatedUser();

GroupAttachments groupAttachments = this.groupAttachmentsDAO.getAttachmenById(attachId);

GroupMembers groupMembers = this.groupMembersService.returnMembersMatchingUsernameAccountId(person.getUsername(),

groupAttachments.getGroupId());

if (!(groupMembers == null)) {

if (person.getUsername().equals(groupMembers.getMemberUsername())) {

try {

return Paths.get(msg + groupAttachments.getGroupId() + "/" +

groupAttachments.getFileIdentifier());

} catch (Exception ignored) {

return null;

}

}

return null;

} else {

return null;

}

}

+1

您正在阅读的一切到内存中,不这样做......的'Files.readAllBytes'加载整个'2Gb'到内存中。根本不要。延迟加载,而不是首先加载它,逐个阅读并直接流式传输。改为使用'Files.copy(Path,OutputStream)'。 –

+0

复制将流式传输,而不是加载它。请阅读评论... –

+0

@ M.Deinum:抱歉误读。我已经更新了代码,并且用Files.copy(path,outputStream)尝试过,效果很好。我已经在主帖中发布了更新的代码,请你检查是否有可能的优化。谢谢。 –

java 防止文件下载_Spring,Java:流式文件下载以避免内存不足错误相关推荐

  1. 对象存储 OSS 文件下载方法:流式下载和本地下载

    OSS Java SDK提供了丰富的文件下载方式: 流式下载 下载到本地文件 创建对象 ossClient 实例化后,可以先进行一步非空判断,确定该对象存储中有我们要找的 bucket 和 文件.判断 ...

  2. Java:以CSV格式流式传输JDBC结果集

    在上一篇文章中 ,我展示了如何将java.sql.ResultSet转换为JSON并将其流回调用方. 这篇文章是关于以CSV格式流式传输的. 流式传输使您可以一点一点地传输数据,而不必将所有数据都加载 ...

  3. php下载二进制流文件下载,从MySQL流式传输二进制文件以使用PHP下载

    我有一个存储在MySQL表longblob字段中的Excel电子表格.我需要检索此数据,然后将其作为可下载文件传输给用户,最好不要先将其写入磁盘. 可能? 编辑 – 呃,刚想通了--发表在下面的答案. ...

  4. JStorm—实时流式计算框架入门介绍

    JStorm介绍   JStorm是参考storm基于Java语言重写的实时流式计算系统框架,做了很多改进.如解决了之前的Storm nimbus节点的单点问题.   JStorm类似于Hadoop ...

  5. 20190827 On Java8 第十四章 流式编程

    第十四章 流式编程 流的一个核心好处是,它使得程序更加短小并且更易理解.当 Lambda 表达式和方法引用(method references)和流一起使用的时候会让人感觉自成一体.流使得 Java ...

  6. JavaSwing_1.1: FlowLayout(流式布局)

    本文链接: http://blog.csdn.net/xietansheng/article/details/72814541 Java Swing 图形界面开发(目录) 1. 概述 官方JavaDo ...

  7. 任意java程序都可以是servlet吗_C#从Java servlet中获取文件流实现任意文件下载

    目的: 从C#创建的客户端中向Java创建的servlet提交请求(不知道这是否算作严格的CS架构),servet返回一个文件流( 任意格式的文件 ),然后通过C#获取该文件流并保存到本地,使得文件可 ...

  8. java流式上传下载_精讲RestTemplate第6篇-文件上传下载与大文件流式下载

    C++Templates(第2版英文版) 123.24元 (需用券) 去购买 > 本文是精讲RestTemplate第6篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在S ...

  9. 实现文件下载的java代码

    实现文件下载的java代码 //这是实现下载类(servlet),详细思路代码例如以下: //也可连接数据库 package com.message; import javax.servlet.*; ...

最新文章

  1. 线性代数的本质与几何意义 02. 线性组合、张成的空间、基(3blue1brown 咪博士 图文注解版)...
  2. $‘\r‘: command not found解决方法
  3. iPhone XS MAX全球首碎!一看官方维修价 网友:修不起!
  4. linux中pthread_kill函数详解
  5. Python3打印当前系统时间
  6. Java注释--单行注释、多行注释、文档注释
  7. 适用于openvino 2020.2的yolov5的docker制作
  8. WPF 动态图片按钮
  9. JavaScript中数组高级编程实践
  10. win7开启telnet工具
  11. python 麦克风人声检测_物超所值的人声麦克风推荐
  12. IntelliJ IDEA使用教程(动图详解):Mac 系统下安装 IntelliJ IDEA
  13. linux怎么下载ftp文件夹,命令行 - 如何在Linux上通过FTP递归下载文件夹
  14. 愿你我,能被这世界温柔以待
  15. 路由器硬改内存笔记1-理论
  16. 实现mac状态栏图标的隐藏
  17. 输出某年某月某日的c语言程序,输入某年某月某日,输出这是今年的第几天,C语言问题...
  18. matlab模拟塞曼图谱,塞曼效应理论与实验分析.doc
  19. sql语句实现查询实例
  20. 关于双击此电脑、回收站、控制面板等提示找不到应用程序解决方案

热门文章

  1. mysql 非正常关闭,centos非正常关机后,mysql竟然启动不了
  2. 查看target/classes/.../dao/文件夹下,发现只有mapper的class文件,而没有xml文件 的解决方法。
  3. asp.net panel 加html,ASP.NET 页面中动态增加的控件、添加事件
  4. keyvaluepair_C# KeyValuePairTKey,TValue的用法【转】 .
  5. oauth最后的确认按钮_spring-oauth集成cas单点登录,登陆完成进入授权页面后,按回退按钮进入404页面的问题...
  6. php时间函数 1天,PHP函数第20款:两个时间相差的天数SubTime,不满1天按1天算
  7. sql 树状结构中知道 父节点与孙节点_集群环境中使用Zookeeper实现分布式幂等控制...
  8. smarty中打印php变量,smarty用php标签怎么输出变量
  9. python【数据结构与算法】红黑树概念辨析
  10. K-Means原理解析