前言

最近严查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()));
}
  1. 问题核心在于返回ResponseEntity<InputStreamResource>
  2. ResponseEntity是SpringMVC里统一封装的返回值response信息
  3. InputStreamResource则是接收一个输入流InputStream的结果集
  4. 然后可以设置浏览器缓存,这个对用户刷新页面挺重要的
  5. 对于图片和js等,需要设置contentType为png或者js等

SpringMVC,SpringBoot文件下载的更多相关文章

  1. spring springMvc spring-boot spring-cloud分别是什么

    本文来源于:克己习礼成仁   的<spring springMvc spring-boot spring-cloud分别是什么> 什么是spring 关于spring的定义无论是从官方还是 ...

  2. springmvc springboot 跨域问题(CORS)

    官方文档:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cors.html springmvc s ...

  3. 基于 Nginx XSendfile + SpringMVC 进行文件下载

    转自:http://denger.iteye.com/blog/1014066 基于 Nginx XSendfile + SpringMVC 进行文件下载 PS:经过实际测试,通过 nginx 提供文 ...

  4. SpringMVC实现文件下载的两种方式及多文件下载

    1.传统方法 @RequestMapping("/download") public String download( String fileName ,String filePa ...

  5. springmvc/springboot开发restful API

    非rest的url写法: 查询 GET /user/query?name=tom 详情 GET /user/getinfo? 创建 POST /user/create?name=tom 修改 POST ...

  6. Spring SpringMVC SpringBoot SpringCloud 注解整理大全

    Spring SpringMVC SpringBoot SpringCloud 注解整理 才开的博客所以放了一篇以前整理的文档,如果有需要添加修改的地方欢迎指正,我会修改的φ(๑˃∀˂๑)♪ Spri ...

  7. 开发者说:Sentinel 流控功能在 SpringMVC/SpringBoot 上的实践

    从用户的视角来感受一个开源项目的成长,是我们推出「开发者说」专栏的初衷,即在开发者进行开源项目选型时,提供更为立体的项目信息.专栏所有内容均来自作者原创/投稿,本文是「开发者说」的第6篇,作者 Jas ...

  8. springmvc实现文件下载

    springmvc实现文件下载 使用springmvc实现文件下载有两种方式,都需要设置response的Content-Disposition为attachment;filename=test2.p ...

  9. SpringMVC & SpringBoot小记

    SpringMVC 1.SpringMVC常用注解 https://blog.csdn.net/lipinganq/article/details/79155072 :@Component.@Serv ...

随机推荐

  1. CSS 去掉inline-block间隙的几种方法

    最近做移动端页面时,经常会用到inline-block元素来布局,但无可避免都会遇到一个问题,就是inline-block元素之间的间隙.这些间隙会导致一些布局上的问题,需要把间隙去掉.对于inlin ...

  2. php解决json_encode输出GB2312中文问题 (数组)

    在 php 中使用 json_encode() 内置函数(php > 5.2)可以使用得 php 中数据可以与其它语言很好的传递并且使用它. 这个函数的功能是将数值转换成json数据存储格式. ...

  3. 树上操作[HAOI 2015]

    树链剖分裸题: 树剖点这里:传送门 代码: #include<bits/stdc++.h> #define sight(c) ('0'<=c&&c<='9') ...

  4. vue2 watch引用类型 失败原因

    vue中watch基本用法: new Vue({ el: '#t1', data: { a: { b: 1, c: 2 }, }, methods: { ch() { this.a.d=5 //不打印 ...

  5. Center OS 7 安装 $$

    资料来自网络,收集整理做个备忘 1. 安装Python # yum install python-setuptools && easy_install pip 2. 安装$$ # pi ...

  6. java基础只关键字final

    final关键字简述 final关键字是在编写java程序中出现频率和很高的关键字,如果想要更好的编写java程序,那么掌握final关键字的运用是非常必要的.让我们先看一下final关键字可以修饰的 ...

  7. git for windows上传项目到github

    软件:git for windows 账户:github账户 1.第一步创建自己的github账号,并创建自己的project,创建完毕之后url如下 https://github.com/ft110 ...

  8. ul li自适应居中导航

    <BODY> <div class="box"> <ul class="nav"> <li>邮箱管理</l ...

  9. 使用腾讯云无服务器云函数(SCF)分析天气数据

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:李想 无服务器云函数(SCF)是腾讯云提供的Serverless执行环境,也是国内首款FaaS(Function as a Service ...

  10. PHP连接LDAP进行登录验证

    基于安全性考虑,准备把PHP做的自动化平台加入ldap登录验证,具体做法如下: 了解背景: LDAP 的全称是"轻量级目录访问协议(Lightweight Directory Access ...