springmvc之下载文件

Easter79
• 阅读 727

springMVC 下载文件

在开发web项目时,我们经常会遇到下载文件的情况。我们下来看下面这个代码:

public void downLoad(HttpServletResponse response, String filename) {
        if (file == null || !file.exists()) {
            return;
        }
        OutputStream out = null;
        try {
            response.reset();
            response.setContentType("application/octet-stream; charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; filename="
                    + file.getName());
            out = response.getOutputStream();
            File file = new File(savePath + fileName);//文件路径
            out.write(FileUtils.readFileToByteArray(file));
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

在之前的servlet中这样的写法非常普遍,但是既然我们使用springmvc框架,不应该在暴露HttpServletResponse 这种j2ee的接口了,所以spring提供了更好、更优雅的实现方式。

@RequestMapping("/download")  
    public ResponseEntity<byte[]> download(String fileName) throws IOException { 
        HttpHeaders headers = new HttpHeaders();  
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);  
        headers.setContentDispositionFormData("attachment", URLEncoder.encode(fileName,"UTF-8")); 
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(mailService.getDownloadFile(fileName)),  
                                          headers, HttpStatus.CREATED);  
    }

我们详细看看这几行代码:

headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

在源码中:

    /**
     * Public constant media type for {@code application/octet-stream}.
     *  */
    public final static MediaType APPLICATION_OCTET_STREAM;

    /**
     * A String equivalent of {@link MediaType#APPLICATION_OCTET_STREAM}.
     */
    public final static String APPLICATION_OCTET_STREAM_VALUE = "application/octet-stream";
    APPLICATION_OCTET_STREAM = MediaType.valueOf(APPLICATION_OCTET_STREAM_VALUE);

这一句的作用相当于

response.setContentType("application/octet-stream; charset=utf-8");

指定contentType为"application/octet-stream",contentType的作用就是用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件。这里的作用就是,告诉浏览器返回的是二进制流数据。

headers.setContentDispositionFormData("attachment", URLEncoder.encode(fileName,"UTF-8")); 

Content-disposition其实可以控制用户请求所得的内容存为一个文件的时候提供一个默认的文件名,文件直接在浏览器上显示或者在访问时弹出文件下载对话框。 如attachment为以附件方式下载 。相当于servlet中:

response.setHeader("Content-Disposition", "attachment; filename="
                    + file.getName());

filename就是显示的下载框中默认的下载文件名。Content-Disposition参数本来是为了在客户端另存文件时提供一个建议的文件名,但是考虑到安全的原因,就从规范中去掉了这个参数。但是由于很多浏览器已经能够支持这个参数,所以只是在规范文档中列出,但是要注意这个不是HTTP/1.1的标准参数。为了让建议的文件名支持中文,使用了URLEncoder.encode(fileName,"UTF-8")。 最后一句代码:

return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(mailService.getDownloadFile(fileName)),  
                                          headers, HttpStatus.CREATED);

这里getDownloadFile()方法就是通过文件名得到文件,在使用这段代码时需要换成自己的实现方式。headers上面已经介绍过了,就是告诉浏览器返回的是二进制流数据(application/octet-stream),以附件的形式打开("attachment;filename=xxx")。并且返回状态码HttpStatus.CREATED(201,代表已创建请求成功并且服务器创建了新的资源。) 最后提醒注意的是,导包的时候不要导错了:

import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
点赞
收藏
评论区
推荐文章
Easter79 Easter79
3年前
vue+axios下载pdf文件流
项目中用到流文件下载的需求,之前使用的方法一直都没问题,但是这次就是下载不下来,查了多种方法终于解决了,方式如下://下载文件downLoadFile(e){letide.target.dataset.id;letnamee.target.dataset.name;
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Souleigh ✨ Souleigh ✨
3年前
前端性能优化 - 雅虎军规
无论是在工作中,还是在面试中,web前端性能的优化都是很重要的,那么我们进行优化需要从哪些方面入手呢?可以遵循雅虎的前端优化35条军规,这样对于优化有一个比较清晰的方向.35条军规1.尽量减少HTTP请求个数——须权衡2.使用CDN(内容分发网络)3.为文件头指定Expires或CacheControl,使内容具有缓存性。4.避免空的
Easter79 Easter79
3年前
SpringMVC与SpringBoot配置文件的加载区别
一、SpringMVC:配置文件在classpath下。在web.xml中配置加载。以下项目为示例其中引用关系为1. applicationContextdao.xml引用了mybatis文件夹中的配置文件2. applicationContextshiro.xml引用了shiro文件夹中的配置文件3. sprin
Easter79 Easter79
3年前
SSM_基于传统web项目
1.这是一个单模块的项目!有四个配置文件,mybaits,spring。springmvc,web.xml!2.web.xml配置文件,导入spring和springmvc的配置文件,spring配置文件中,获取sqlsession,以及关联mybatis的mpper(增删改查)文件3.mybatis的配置文件则可以不用写
Stella981 Stella981
3年前
Maven命令将本地jar打包到maven仓库
一、背景日常开发中,常见的一种情况是在java项目的pom.xml文件中引入依赖版本信息,由于maven中央仓库没有这个jar,我们可以从其他地方下载下来,然后再使用打包方式将下载下来的jar包打包到maven仓库。二、示例1\.依赖ojabc6引入!在这里插入图片描述(https:/
Stella981 Stella981
3年前
SSM_基于传统web项目
1.这是一个单模块的项目!有四个配置文件,mybaits,spring。springmvc,web.xml!2.web.xml配置文件,导入spring和springmvc的配置文件,spring配置文件中,获取sqlsession,以及关联mybatis的mpper(增删改查)文件3.mybatis的配置文件则可以不用写
Easter79 Easter79
3年前
springMVC两种方式实现多文件上传及效率比较
springMVC实现多文件上传的方式有两种,一种是我们经常使用的以字节流的方式进行文件上传,另外一种是使用springMVC包装好的解析器进行上传。这两种方式对于实现多文件上传效率上却有着很大的差距,下面我们通过实例来看一下这两种方式的实现方式,同时比较一下在效率上到底存在着多大的差距。1.下载相关jar包。需要引入的jar出了springMVC的ja
Easter79 Easter79
3年前
SpringMVC 文件下载时 浏览器不能正确显示另存的文件名
问题:通过打印输出流的方式把文件下载到本地,但是在firebox中下载的文件不显示文件的文件名,造成文件不能直接打开,其他浏览器可以直接打开.原因:主要是文件名称中有汉字而没有转码造成firebox浏览器不能正确显示另存的文件名解决方案://提供如下工具类将 文件名编码 就可以啦public s
Wesley13 Wesley13
3年前
Java多线程导致的的一个事物性问题
业务场景我们现在有一个类似于文件上传的功能,各个子站点接受业务,业务上传文件,各个子站点的文件需要提交到总站点保存,文件是按批次提交到总站点的,也就是说,一个批次下面约有几百个文件。      考虑到白天提交这么多文件会影响到子站点其他系统带宽,我们将分站点的文件提交到总站点这个操作过程独立出来,放到晚上来做,具体时间是晚上7:00到早上7:00。
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k