SpringMVC,SpringBoot文件下载
时间:2022-05-04
本文章向大家介绍SpringMVC,SpringBoot文件下载,主要内容包括前言、关于文件存储的设计、地址路径的健壮性、如何使用SpringMVC下载文件、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
前言
最近严查security, 导致原来暴露出去的s3不能用了,不允许public的s3,暂时的折中方案是自己做跳转。于是需要在SpringMVC中实现文件下载功能。
关于文件存储的设计
文件存储通常用作对象存储,业界标准就是AWS s3, 国内的七牛也差不多。不想自建的话,采用这种第三方存储是很方便的。但是,有写地方需要注意。
安全问题
就像这次整改遇到的,权限问题大概是对象存储必须具备的。s3的权限特别多和复杂,可以做到认证user访问; 指定ip访问; 指定IAM Role访问; 指定第三方登陆比如Facebook,google的认证,设置自己的认证,这里是指Cognito。
地址路径的健壮性
review代码的时候发现了几个严重的问题,地址问题尤为重要,简直就是bug一样。首先,db存储的文件路径不应该包含域名前缀,像这次整改图片存储就导致以前db里的数据不能用了。db只能存储相对路径,即当指定改类型前缀后,变化的部分路径。。 然后就是 需要一个域名,对于公开的地址,需要一个域名来维护,而不是直接指定当前的文件服务器。比如一个公开的s3可能是这样的:https://mybucket.s3.amazonaws.com/keyprefix/key. 如果我们变更了s3的bucket,那么这个地址就废弃了,这个很有可能发生的。因此,用一个我们自己的域名指向s3可以屏蔽这个细节。同理,如果写死了文件服务器的地址,当文件服务器变更的时候,公开的文件将全部失效。
如何使用SpringMVC下载文件
我们可以简单的在HttpServletResponse
的OutputStream里写入我们的文件流,这样就可以实现文件下载。但这个做法感觉有点太直接了,推荐使用Spring的ResponseEntity来做。
@RequestMapping(value = "/static/filename")
public ResponseEntity<InputStreamResource>(HttpServletResponse response) {
final ObjectMetadata objectMetadata = s3Object.getObjectMetadata();
return ResponseEntity.ok()
.header("Access-Control-Allow-Origin", "*")
.cacheControl(CacheControl.maxAge(maxAge, TimeUnit.DAYS).cachePublic())
.allow(HttpMethod.GET, HttpMethod.OPTIONS)
.contentLength(objectMetadata.getContentLength())
.contentType(MediaType.valueOf(objectMetadata.getContentType()))
.body(new InputStreamResource(s3Object.getObjectContent()));
}
- 问题核心在于返回
ResponseEntity<InputStreamResource>
-
ResponseEntity
是SpringMVC里统一封装的返回值response信息 -
InputStreamResource
则是接收一个输入流InputStream的结果集 - 然后可以设置浏览器缓存,这个对用户刷新页面挺重要的
- 对于图片和js等,需要设置contentType为png或者js等
- FrameLayout(框架布局)
- WordPress 中变量$allowedposttags 添加自定义HTML属性
- 移动端UC /QQ 浏览器的部分私有Meta 属性
- RelativeLayout(相对布局)
- TableLayout(表格布局)
- 【MindiaX实例】 PHP 在foreach 中获取JSON 单个数据
- 史上十大最严重黑客袭击事件盘点
- LinearLayout(线性布局)
- 服务化了,没想到耦合更加严重?
- 利用好注册的域名
- Android中TextView
- 腾讯 DCI 上线基于集中控制的 SR-TE 方案
- 如何从VS2003升级到VS2008
- js中多个Date对象变量间赋值互相影响
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Mybatis源码学习(三)executor
- Mybatis源码学习(四)拦截器与插件原理
- SpringBoot如何使用注解装配Bean
- Spring Boot 如何快速实现定时任务
- Django 实现文件上传下载API
- 【原创】Spring Boot 如何手写stater
- 【原创】Spring Boot 过滤器、监听器、拦截器的使用
- 关于useState的一切
- 关于useEffect的一切
- (25)Bash数值运算与运算符
- (27)正则表达式
- (28)字符截取命令cut、printf
- (29)字符截取命令awk
- RTSP协议视频平台EasyNVR流媒体服务器音频播放完毕后,视频为什么也会卡住?
- Redis | Redis 有序集合相关命令