ResponseEntity进行下载
项目实例:
@GetMapping("getPermitSignFile")@ApiOperation(value = "获取许可证签名文件")public ResponseEntity<Resource> getPermitSignFile(@ApiParam(name = "permitId", value = "许可证ID") String permitId) throws UnsupportedEncodingException {//判断所要下载的文件ID是否存在!!!//专门有个存图的表在其中查 fileId ,存在才可以下载!!!String fileId = this.service.getPermitSignFileId(permitId);if (!StringUtils.isEmpty(fileId)) {Map<String, Object> file = this.documentService.loadAsResource(fileId);//这种方式返回body 内容!!!ResponseEntity.BodyBuilder ok = ResponseEntity.ok().header("Content-Disposition", new String[]{"attachment; filename= \"" + URLEncoder.encode((String) file.get("fileName"), "UTF-8") + "\""})).body((Resource) file.get("resource"));return ok;}return null;}
解释上文:
ResponseEntity概念是可以添加HttpStatus状态码的HttpEntity的扩展类;那么不难推测出这个OK状态其实就是HttpStatus状态码
//无参ok
public static ResponseEntity.BodyBuilder ok() {return status(HttpStatus.OK);}
HttpStatus状态码中代表OK的是200
BodyBuilder又是什么鬼:
通过ResponseEntity的结构,我们知道BodyBuilder是ResponseEntity中的接口
直译:
定义一个可以添加body到response entity的builder
简单粗暴理解:
ResponseEntity可以通过这个builder返回任意类型的body内容。
BodyBuilder源码:
public interface BodyBuilder extends ResponseEntity.HeadersBuilder<ResponseEntity.BodyBuilder> {ResponseEntity.BodyBuilder contentLength(long var1);ResponseEntity.BodyBuilder contentType(MediaType var1);<T> ResponseEntity<T> body(@Nullable T var1);}
通过BodyBuilder源码,不难发现
BodyBuilder接口中的body方法的参数可以为空值(有@Nullable标签名字推测其允许空值)
loadAsResource 接口(直接用):
public Map<String, Object> loadAsResource(String fileId) {Map<String, Object> result = new HashedMap();FileInfo fileInfo = (FileInfo)this.fileInfoRepository.findOne(fileId);if (fileInfo != null) {String fileName = fileInfo.getFileOriginalName();try {Resource resource = new InputStreamResource(MinioUtil.getInstance().getObjectStream(fileInfo.getFileStorageId()));if (!resource.exists() && !resource.isReadable()) {throw new StorageFileNotFoundException("读取文件失败: " + fileName);} else {result.put("fileName", fileName);result.put("resource", resource);return result;}} catch (MalformedURLException var6) {throw new StorageFileNotFoundException("读取文件失败: " + fileName, var6);} catch (Exception var7) {var7.printStackTrace();throw new StorageFileNotFoundException("读取文件失败: " + fileName, var7);}} else {throw new StorageFileNotFoundException("读取文件失败: " + fileId);}}
Resource(应该可以直接用):
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package org.springframework.core.io;import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;public interface Resource extends InputStreamSource {boolean exists();boolean isReadable();boolean isOpen();URL getURL() throws IOException;URI getURI() throws IOException;File getFile() throws IOException;long contentLength() throws IOException;long lastModified() throws IOException;Resource createRelative(String var1) throws IOException;String getFilename();String getDescription();
}
MinioUtil:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package com.richfit.ip.document.minio;import com.richfit.ip.utils.StringUtil;
import com.richfit.ip.webmvc.SpringContextHelper;
import io.minio.MinioClient;
import io.minio.Result;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidArgumentException;
import io.minio.errors.InvalidBucketNameException;
import io.minio.errors.NoResponseException;
import io.minio.messages.Item;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmlpull.v1.XmlPullParserException;public class MinioUtil {private static final Logger log = LoggerFactory.getLogger(MinioUtil.class);private static MinioUtil minioUtil;private MinioProperty minioProperty = (MinioProperty)SpringContextHelper.getBean(MinioProperty.class);private MinioClient minioClient;private static int RETRY_NUM = 3;public static MinioUtil getInstance() {if (null != minioUtil) {return minioUtil;} else {Class var0 = MinioUtil.class;synchronized(MinioUtil.class) {if (null == minioUtil) {minioUtil = new MinioUtil();}}return minioUtil;}}private MinioUtil() {if (null == this.minioProperty) {this.minioProperty = new MinioProperty();}this.init();}private void init() {try {if (StringUtils.isNotEmpty(this.minioProperty.getUrl()) && StringUtils.isNotEmpty(this.minioProperty.getAccessKey()) && StringUtils.isNotEmpty(this.minioProperty.getSecretKey())) {this.minioClient = new MinioClient(this.minioProperty.getUrl(), this.minioProperty.getAccessKey(), this.minioProperty.getSecretKey(), false);if (!StringUtil.isNullOrEmpty(this.minioProperty.getDefaultBucketName())) {this.createBucket(this.minioProperty.getDefaultBucketName());}}} catch (Exception var2) {log.error("初始化minio客户端失败:", var2);}}public MinioClient getMinioClient() {return this.minioClient;}public boolean createBucket(String bucketName) {boolean isCreated;try {if (!this.minioClient.bucketExists(bucketName)) {this.minioClient.makeBucket(bucketName);}isCreated = true;} catch (Exception var4) {isCreated = false;log.error("创建Bucket失败", var4);var4.printStackTrace();}return isCreated;}public String uploadStream(String bucketName, String minioFilePath, InputStream inputStream, String mediaType) {if (StringUtils.isBlank(mediaType)) {mediaType = "application/octet-stream";}try {this.putObjectWithRetry(bucketName, minioFilePath, inputStream, mediaType);return this.cleanUrlByRemoveIp(this.minioClient.getObjectUrl(bucketName, minioFilePath));} catch (Exception var6) {log.error("上传文件流发生错误:", var6);throw new RuntimeException(var6);}}public String uploadStream(String minioFilePath, InputStream inputStream, String mediaType) {return this.uploadStream(this.minioProperty.getDefaultBucketName(), minioFilePath, inputStream, mediaType);}public String uploadFile(String minioFilePath, String localFile, String mediaType) {return this.uploadFile(this.minioProperty.getDefaultBucketName(), minioFilePath, localFile, mediaType);}public String uploadFile(String bucketName, String minioFilePath, String localFile, String mediaType) {if (StringUtils.isBlank(mediaType)) {mediaType = "application/octet-stream";}try {this.putObjectWithRetry(bucketName, minioFilePath, localFile, mediaType);return this.cleanUrlByRemoveIp(this.minioClient.getObjectUrl(bucketName, minioFilePath));} catch (Exception var6) {log.error("上传文件发生错误:", var6);throw new RuntimeException(var6);}}public List<MinioFile> listFilesSwap(String bucketName, String prefix, boolean recursive) {return this.swapResultToEntityList(this.minioClient.listObjects(bucketName, prefix, recursive));}public Iterable<Result<Item>> listFiles(String bucketName, String prefix, boolean recursive) {return this.minioClient.listObjects(bucketName, prefix, recursive);}public List<MinioFile> listFilesByBucketNameSwap(String bucketName) {return this.swapResultToEntityList(this.minioClient.listObjects(bucketName, (String)null, true));}public Iterable<Result<Item>> listFilesByBucketName(String bucketName) {return this.minioClient.listObjects(bucketName, (String)null, true);}public Iterable<Result<Item>> listFilesByBucketAndPrefix(String bucketName, String prefix) {return this.minioClient.listObjects(bucketName, prefix, true);}public List<MinioFile> listFilesByBucketAndPrefixSwap(String bucketName, String prefix) {return this.swapResultToEntityList(this.minioClient.listObjects(bucketName, prefix, true));}private MinioFile swapResultToEntity(Result<Item> result) {MinioFile entity = new MinioFile();try {if (result.get() != null) {Item item = (Item)result.get();entity.setObjectName(this.cleanUrlByRemoveIp(item.objectName()));entity.setIsDir(item.isDir());entity.setEtag(item.etag());entity.setLastModified(item.lastModified());entity.setObjectSize(item.objectSize());entity.setStorageClass(item.storageClass());}} catch (Exception var4) {log.error("获取文件信息出错, e={}", var4.getMessage());}return entity;}private String cleanUrlByRemoveIp(String s) {return s;}private List<MinioFile> swapResultToEntityList(Iterable<Result<Item>> results) {List<MinioFile> files = new ArrayList();Iterator var3 = results.iterator();while(var3.hasNext()) {Result<Item> result = (Result)var3.next();files.add(this.swapResultToEntity(result));}return files;}public void putObjectWithRetry(String bucketName, String objectName, InputStream stream, String contentType) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidArgumentException, NoResponseException, InvalidBucketNameException, XmlPullParserException, InternalException {int current = 0;boolean isSuccess = false;while(!isSuccess && current < RETRY_NUM) {try {this.minioClient.putObject(bucketName, objectName, stream, contentType);stream.close();isSuccess = true;} catch (ErrorResponseException var8) {log.warn("[minio] putObject stream, ErrorResponseException occur for time =" + current, var8);++current;}}if (current == RETRY_NUM) {log.error("[minio] putObject, backetName={}, objectName={}, failed finally!");}}public String getObjectUrl(String objectName) throws Exception {return this.getObjectUrl(this.minioProperty.getDefaultBucketName(), objectName, 86400);}public void removeObject(String objectName) throws Exception {this.minioClient.removeObject(this.minioProperty.getDefaultBucketName(), objectName);}public void removeObject(String bucketName, String objectName) throws Exception {this.minioClient.removeObject(bucketName, objectName);}public void removeObjects(String bucketName, List<String> objectNames) throws Exception {this.minioClient.removeObject(bucketName, objectNames);}public void removeObjects(List<String> objectNames) throws Exception {this.minioClient.removeObject(this.minioProperty.getDefaultBucketName(), objectNames);}public String getObjectUrl(String bucketName, String objectName) throws Exception {return this.getObjectUrl(bucketName, objectName, 86400);}public InputStream getObjectStream(String bucketName, String objectName) throws Exception {return this.minioClient.getObject(bucketName, objectName);}public InputStream getObjectStream(String objectName) throws Exception {return this.getObjectStream(this.minioProperty.getDefaultBucketName(), objectName);}public String getObjectUrl(String bucketName, String objectName, Integer expires) throws Exception {return this.minioClient.presignedGetObject(bucketName, objectName, expires);}public void putObjectWithRetry(String bucketName, String objectName, String fileName, String contentType) throws InvalidBucketNameException, NoSuchAlgorithmException, InsufficientDataException, IOException, InvalidKeyException, NoResponseException, XmlPullParserException, ErrorResponseException, InternalException, InvalidArgumentException, InsufficientDataException {int current = 0;boolean isSuccess = false;while(!isSuccess && current < RETRY_NUM) {try {this.minioClient.putObject(bucketName, objectName, fileName, contentType);isSuccess = true;} catch (ErrorResponseException var8) {++current;log.debug("[minio] putObject file, ErrorResponseException occur!");}}if (current == RETRY_NUM) {log.error("[minio] putObject, backetName={}, objectName={}, failed finally!");}}public static void main(String[] args) throws Exception {List<MinioFile> files = getInstance().listFilesByBucketNameSwap("image");String url = getInstance().getObjectUrl("image", ((MinioFile)files.get(0)).getObjectName());}
}
@RequestMapping("/testResponseEntity")public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException{byte [] body = null;ServletContext servletContext = session.getServletContext();InputStream in = servletContext.getResourceAsStream("/files/abc.txt");body = new byte[in.available()];in.read(body);HttpHeaders headers = new HttpHeaders();headers.add("Content-Disposition", "attachment;filename=abc.txt");HttpStatus statusCode = HttpStatus.OK;ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(body, headers, statusCode);return response;}
其中对Content-Disposition 响应头 进行解析:
在页面内打开代码:
File file = new File("rfc1806.txt");String filename = file.getName();response.setHeader("Content-Type","text/plain");response.addHeader("Content-Disposition","inline;filename=" + new String(filename.getBytes(),"utf-8"));response.addHeader("Content-Length","" + file.length());
弹出保存框代码:
File file = new File("rfc1806.txt");String filename = file.getName();response.setHeader("Content-Type","text/plain");response.addHeader("Content-Disposition","attachment;filename=" + new String(filename.getBytes(),"utf-8"));response.addHeader("Content-Length","" + file.length());
ResponseEntity进行下载相关推荐
- SpringMVC中文件的上传和下载
1 文件下载 ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文. 使用ResponseEntity实现下载文件功能 package com.spr ...
- SpringMVC通过ResponseEntity实现文件下载
使用ResponseEntity实现下载文件的功能 所下载的图片路径如图所示: Controller: @RequestMapping("/testDown") public Re ...
- 普通文件下载 + 前端获取后端返回的文件流并下载
参考资料 前端接受后端文件流并下载的几种方法 ajax 请求二进制流 图片 文件 XMLHttpRequest 请求并处理二进制流数据 之最佳实践 ajax请求二进制流进行处理(ajax异步下载文件) ...
- SpringMVC处理Json、文件上传、拦截器
SpringMVC处理Json.文件上传.拦截器 : 处理JSON 链接 http://repo1.maven.org/maven2/com/fasterxml/jackson/core/ 步骤 编写 ...
- SpringBoot(2)
5.Web开发 5.1.SpringMVC自动配置概览 Spring Boot provides auto-configuration for Spring MVC that works well w ...
- b站尚硅谷springmvc学习视频:springmvc文档
文章目录 一.SpringMVC简介 (b站尚硅谷springmvc学习视频:springmvc文档) 1.什么是MVC 2.什么是SpringMVC 3.SpringMVC的特点 二.HelloWo ...
- SpringMVC-详解
文章目录 一.SpringMVC简介 1.什么是MVC 2.什么是SpringMVC 3.SpringMVC的特点 二.HelloWorld 1.开发环境 2.创建maven工程 a>添加web ...
- SpringMVC的相关知识
目录 SpringMVC 一.SpringMVC简介 1.概述 2.特点 二.入门案例 1.创建一个webapp项目 2.导入相关包 3.配置web.xml文件 4.创建请求控制器 5.配置Sprin ...
- SpringMVC笔记-尚硅谷(杨博超)
文章目录 一.SpringMVC简介 1.什么是MVC 2.什么是SpringMVC 3.SpringMVC的特点 二.HelloWorld 1.开发环境 2.创建maven工程 a>添加web ...
最新文章
- 【Python】Python3中的str和bytes
- 手机端部署的超分机器学习模型-MobiSR
- oracle数据库从入门到精通之三
- 算法题12 数组中所有的逆序对
- smarty二维foreach示例[顺代一维数组],再次加强版
- oracle cdc 关闭,Oracle CDC部署流程
- css动画详解 (transition animation)
- FireMonkey 保存图片到JPG的方法 BMP转JPG
- Java-IO流-实例
- es6数组初始化_说一下自己常用的es6的功能
- 骑士人才系统后台用户名密码重设工具源码
- CVE-2015-5254(ActiveMQ反序列化漏洞复现)
- 从期货开户公司分享交易所手续费返还
- 网页打开慢,甚至突然打不开?图片刷新不出来?多半是DNS的问题!
- 只可顺守不可逆取书法_关于如何练字,分享给想练好书法的人
- 【回顾】巨杉数据库中标东莞农商银行非结构化内容管理平台项目
- 【头歌】重生之机器学习-线性回归
- 职称论文发表的字数不够怎么办
- 电脑外设(I/O)简介:键盘鼠标
- 详细解读《个人所得税专项附加扣除暂行办法》
热门文章
- 计算机安装Hp1005打印机,hp1005打印机驱动官方版
- 如何用python的turtle画五角星_海龟编辑器五角星怎么画 绘制五角星就是这么简单...
- C# WPF 基于Socket的企业聊天软件IM(源码)
- 微信里的小程序怎么制作
- 【分享】免梯子的GPT,玩 ChatGPT 的正确姿势
- 让企业订单交期满足率提升3.5倍,新一代APS(高级生产计划与排程系统)是什么样的?
- Spring Boot使用@RepeatSubmit 防止重复提交
- fiyme android底层,魅族首批Android 10底层Flyme于今日正式推送
- 【Linux 操作系统】Ubuntu 基础操作 基础命令 热键 man手册使用 关机 重启等命令使用
- css3实现简单的文字动画效果