<div>
<a href="/Cyberspace/main/downloadFile.do?fileName=模板.xlsx">模板下载</a>
</div>

方案一:

    // 文件下载
@RequestMapping(value = "/downloadFile")
public ResponseEntity<byte[]> downloadFile() throws IOException {
String basePath = "F:/testDir/";
String fileName = "ChromeStandaloneV45.0.2454.101.exe";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", URLEncoder.encode(fileName, "utf-8"));//这里用URLEncoder.encode是为了解决文件名中的中文乱码问题
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(new File(basePath + fileName)), headers, HttpStatus.CREATED);
}

配置xxx-servelt.xml

<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8" index="0"></constructor-arg><!-- 避免出现乱码 -->
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
</list>
</property>
</bean>
<!-- 避免IE出现下载JSON文件的情况 -->
<bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
<bean id="byteArrayHttpMessageConverter" class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
<!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="byteArrayHttpMessageConverter" />
<ref bean="stringHttpMessageConverter" />
<ref bean="mappingJacksonHttpMessageConverter" /><!-- json转换器 -->
</list>
</property>
</bean>

方案二:通过Response获得输出流,以流的形式下载文件。以下代码大部分是一样的,自行选择

/**
* 文件下载
*
* @param path
* 文件路径(绝对)
* @param response
* 响应对象
*/
public static void download(String path, HttpServletResponse response) {
File file = new File(path);
InputStream fis = null;
OutputStream os = null;
try {
if (!file.exists()) {
response.getWriter().print("文件不存在");
}
// 以流的形式下载文件
fis = new BufferedInputStream(new FileInputStream(file));
// 设置响应报头
response.reset();
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file.getName(), ENCODING));
response.addHeader("Content-Length", "" + file.length());
response.setContentType(MIME_TYPE_BIN);
response.setCharacterEncoding(ENCODING); // 写入响应流数据
os = new BufferedOutputStream(response.getOutputStream());
byte[] bytes = new byte[1024];
while (fis.read(bytes) != -1) {
os.write(bytes);
}
} catch (Throwable e) {
if (e instanceof ClientAbortException) {
// 浏览器点击取消
LOGGER.info("用户取消下载!");
} else {
e.printStackTrace();
}
} finally {
try {
if (os != null) {
os.close();
}
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
} }
} /**
* 下载服务器已存在的文件,支持断点续传
*
* @param request
* 请求对象
* @param response
* 响应对象
* @param path
* 文件路径(绝对)
*/
public static void download(HttpServletRequest request, HttpServletResponse response, File proposeFile) {
LOGGER.debug("下载文件路径:" + proposeFile.getPath());
InputStream inputStream = null;
OutputStream bufferOut = null;
try {
// 设置响应报头
long fSize = proposeFile.length();
response.setContentType("application/x-download");
// Content-Disposition: attachment; filename=WebGoat-OWASP_Developer-5.2.zip
response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(proposeFile.getName(), ENCODING));
// Accept-Ranges: bytes
response.setHeader("Accept-Ranges", "bytes");
long pos = 0, last = fSize - 1, sum = 0;// pos开始读取位置; last最后读取位置; sum记录总共已经读取了多少字节
if (null != request.getHeader("Range")) {
// 断点续传
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
try {
// 情景一:RANGE: bytes=2000070- 情景二:RANGE: bytes=2000070-2000970
String numRang = request.getHeader("Range").replaceAll("bytes=", "");
String[] strRange = numRang.split("-");
if (strRange.length == 2) {
pos = Long.parseLong(strRange[0].trim());
last = Long.parseLong(strRange[1].trim());
} else {
pos = Long.parseLong(numRang.replaceAll("-", "").trim());
}
} catch (NumberFormatException e) {
LOGGER.error(request.getHeader("Range") + " is not Number!");
pos = 0;
}
}
long rangLength = last - pos + 1;// 总共需要读取的字节
// Content-Range: bytes 10-1033/304974592
String contentRange = new StringBuffer("bytes ").append(pos).append("-").append(last).append("/").append(fSize).toString();
response.setHeader("Content-Range", contentRange);
// Content-Length: 1024
response.addHeader("Content-Length", String.valueOf(rangLength)); // 跳过已经下载的部分,进行后续下载
bufferOut = new BufferedOutputStream(response.getOutputStream());
inputStream = new BufferedInputStream(new FileInputStream(proposeFile));
inputStream.skip(pos);
byte[] buffer = new byte[1024];
int length = 0;
while (sum < rangLength) {
length = inputStream.read(buffer, 0, ((rangLength - sum) <= buffer.length ? ((int) (rangLength - sum)) : buffer.length));
sum = sum + length;
bufferOut.write(buffer, 0, length);
}
} catch (Throwable e) {
if (e instanceof ClientAbortException) {
// 浏览器点击取消
LOGGER.info("用户取消下载!");
} else {
LOGGER.info("下载文件失败....");
e.printStackTrace();
}
} finally {
try {
if (bufferOut != null) {
bufferOut.close();
}
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} public static void downloadWithoutEncode(HttpServletRequest request, HttpServletResponse response, File proposeFile) {
LOGGER.debug("下载文件路径:" + proposeFile.getPath());
InputStream inputStream = null;
OutputStream bufferOut = null;
try {
// 设置响应报头
long fSize = proposeFile.length();
response.setContentType("application/x-download");
response.addHeader("Content-Disposition", "attachment; filename=" + proposeFile.getName());
response.setHeader("Accept-Ranges", "bytes");
long pos = 0, last = fSize - 1, sum = 0;// pos开始读取位置; last最后读取位置; sum记录总共已经读取了多少字节
if (null != request.getHeader("Range")) {
// 断点续传
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
try {
// 情景一:RANGE: bytes=2000070- 情景二:RANGE: bytes=2000070-2000970
String numRang = request.getHeader("Range").replaceAll("bytes=", "");
String[] strRange = numRang.split("-");
if (strRange.length == 2) {
pos = Long.parseLong(strRange[0].trim());
last = Long.parseLong(strRange[1].trim());
} else {
pos = Long.parseLong(numRang.replaceAll("-", "").trim());
}
} catch (NumberFormatException e) {
LOGGER.error(request.getHeader("Range") + " is not Number!");
pos = 0;
}
}
long rangLength = last - pos + 1;// 总共需要读取的字节
// Content-Range: bytes 10-1033/304974592
String contentRange = new StringBuffer("bytes ").append(pos).append("-").append(last).append("/").append(fSize).toString();
response.setHeader("Content-Range", contentRange);
// Content-Length: 1024
response.addHeader("Content-Length", String.valueOf(rangLength)); // 跳过已经下载的部分,进行后续下载
bufferOut = new BufferedOutputStream(response.getOutputStream());
inputStream = new BufferedInputStream(new FileInputStream(proposeFile));
inputStream.skip(pos);
byte[] buffer = new byte[1024];
int length = 0;
while (sum < rangLength) {
length = inputStream.read(buffer, 0, ((rangLength - sum) <= buffer.length ? ((int) (rangLength - sum)) : buffer.length));
sum = sum + length;
bufferOut.write(buffer, 0, length);
}
} catch (Throwable e) {
if (e instanceof ClientAbortException) {
// 浏览器点击取消
LOGGER.info("用户取消下载!");
} else {
LOGGER.info("下载文件失败....");
e.printStackTrace();
}
} finally {
try {
if (bufferOut != null) {
bufferOut.close();
}
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
* @param path
* 文件路径(绝对)
* @param response
* 响应对象
* @return
*/
public static Boolean download(String path, HttpServletResponse response, String filename) {
Boolean isBoolean = false;
File file = new File(path);
InputStream fis = null;
OutputStream os = null;
try {
if (!file.exists()) {
response.getWriter().print("文件不存在");
}
// 以流的形式下载文件
fis = new BufferedInputStream(new FileInputStream(file));
// 设置响应报头
response.reset();
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename.trim(), ENCODING));
response.addHeader("Content-Length", "" + file.length());
response.setContentType(MIME_TYPE_BIN);
response.setCharacterEncoding(ENCODING);
// 写入响应流数据
os = new BufferedOutputStream(response.getOutputStream());
byte[] bytes = new byte[1024];
while (fis.read(bytes) != -1) {
os.write(bytes);
}
isBoolean = true;
} catch (Throwable e) {
if (e instanceof ClientAbortException) {
// 浏览器点击取消
isBoolean = false;
LOGGER.info("用户取消下载!");
} else {
isBoolean = false;
e.printStackTrace();
}
} finally {
try {
if (os != null) {
os.close();
}
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return isBoolean;
}

Spring MVC文件下载的更多相关文章

  1. spring mvc 文件下载 get请求解决中文乱码问题

    方案简写,自己或有些基础的可以看懂,因为没时间写的那么详细 方案1 spring mvc解决get请求中文乱码问题, 在tamcat中server.xml文件 URIEncoding="UT ...

  2. spring mvc 文件下载

    在controller中进行代码编写: @RequestMapping("/download") public ResponseEntity<byte[]> downl ...

  3. Spring MVC 文件下载时候 发现IE不支持

    @RequestMapping("download") public ResponseEntity<byte[]> download(Long fileKey) thr ...

  4. Spring MVC 的文件下载

    在看Spring MVC文件下载之前请先看Spring MVC文件上传 地址:http://www.cnblogs.com/dj-blog/p/7535101.html 文件下载比较简单,在超链接中指 ...

  5. Spring MVC教程——检视阅读

    Spring MVC教程--检视阅读 参考 Spring MVC教程--一点--蓝本 Spring MVC教程--c语言中午网--3.0版本太老了 Spring MVC教程--易百--4.0版本不是通 ...

  6. Spring MVC 文件上传 & 文件下载

    索引: 开源Spring解决方案--lm.solution 参看代码 GitHub: pom.xml WebConfig.java index.jsp upload.jsp FileUploadCon ...

  7. spring mvc的excel报表文件下载时流的冲突解决

    在jsp或者在servlet中有时要用到 response.getOutputStream(),但是此时会在后台报这个错误java.lang.IllegalStateException: getOut ...

  8. Http请求中Content-Type讲解以及在Spring MVC中的应用

    引言: 在Http请求中,我们每天都在使用Content-type来指定不同格式的请求信息,但是却很少有人去全面了解content-type中允许的值有多少,这里将讲解Content-Type的可用值 ...

  9. Spring MVC 学习总结(三)——请求处理方法Action详解

    Spring MVC中每个控制器中可以定义多个请求处理方法,我们把这种请求处理方法简称为Action,每个请求处理方法可以有多个不同的参数,以及一个多种类型的返回结果. 一.Action参数类型 如果 ...

随机推荐

  1. Chapter 4

    1.Python中有四种函数:全局函数,局部函数,lambda函数,方法.其中全局函数与局部函数对比理解,局部函数就是定义在某函数之内的函数,否则就是全局函数,lambda函数就是表达式,方法就跟对象 ...

  2. POJ 2484

    A Funny Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3861   Accepted: 2311 Desc ...

  3. POJ 2101

    #include <iostream> #include <algorithm> #include <cmath> using namespace std; int ...

  4. 2014多校第十场1002 || HDU 4972 A simple dynamic programming problem

    题目链接 题意 : 每次无论哪个队投进一个篮球,就记下现在两队比分的差值,问你最后的结果有多少种情况. 思路 : 该题实在是不好理解,最后的结果有多少种情况就是说不管中间过程怎么来的,只要最后结果不一 ...

  5. 2014多校第七场1005 || HDU 4939 Stupid Tower Defense (DP)

    题目链接 题意 :长度n单位,从头走到尾,经过每个单位长度需要花费t秒,有三种塔: 红塔 :经过该塔所在单位时,每秒会受到x点伤害. 绿塔 : 经过该塔所在单位之后的每个单位长度时每秒都会经受y点伤害 ...

  6. hdu 4768 Flyer 二分

    思路:由于最多只有一个是奇数,所以二分枚举这个点,每次判断这个点的左边区间段所有点的和作为 二分的依据. 代码如下: #include<iostream> #include<cstd ...

  7. 基于Mongodb的轻量级领域驱动框架(序)

    混园子也有些年头了,从各个大牛那儿学了很多东西.技术这东西和中国的料理一样,其中技巧和经验,代代相传(这不是舌尖上的中国广告).转身回头一望,几年来自己也积累了一些东西,五花八门涉猎到各种方向,今日开 ...

  8. maven也是apache下的项目

    maven也是apache下的项目,你看maven官网了,域名都在Apache下

  9. OpenStack学习系列-----第二篇 由一个错误看理解整个架构的重要性

    看了openstack没几天,然后就开始试着用Java调用所有的API,第一步得到Credentials的时候成功了,然后第二步,传参数使所有的server信息都列出来的时候报错404.具体描述如下( ...

  10. iOS iPhone iPad 各种控件默认高度

    iPhone iPad 各种控件默认高度 注意:这些是ios7之前的,ios7之后(包括ios7)有改动,我会在后面标注出来 iPhone和iPad下各种常见控件的宽度和标准是一样的,所以这里就用iP ...