SpringMVC中文件下载
3. SpringMVC中文件下载
3.1 文件下载的流程
# springmvc中文件下载1. 定义用户将服务器中文件下载到自己本地计算机中过程称之为文件下载2. 开发文件下载1). 定位系统中哪些文件需要用户下载2). 将需要下载文件放入指定下载目录中3). 开发一个页面提供一个文件下载链接4). 开发下载Controller
- 开发jsp页面提供一个文件下载链接
<h1>文件下载</h1><a href="${pageContext.request.contextPath}/file/download?fileName=aa.txt">aa.txt</a>
- 开发下载Controller
@Controller@RequestMapping("file")public class FileController { // 用来处理文件下载 请求对应响应输出流 @RequestMapping("download") public void download(String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException { System.out.println("下载文件的名称:" + fileName); // 1. 根据下载相对目录获取下载目录在服务器部署之后绝对目录 String realPath = request.getSession().getServletContext().getRealPath("/down"); // 2. 通过文件输入流读取文件 FileInputStream is = new FileInputStream(new File(realPath, fileName)); // 3. 获取响应输出流 response.setContentType("text/plain;charset=UTF-8"); // 4. 附件下载 attachment 附件 inline 在线打开(默认值) response.setHeader("content-disposition", "attachment;fileName=" + fileName); // 5. 处理下载流复制 ServletOutputStream os = response.getOutputStream(); int len; byte[] b = new byte[1024]; while(true){ len = is.read(b); if(len == -1) break; os.write(b, 0, len); } // 释放资源 os.close(); is.close(); }}
测试
3.2 文件下载的细节
- 当在线打开无法打开时,会自动进行附件下载
文件下载有两种形式,一种是直接在页面打开,一种是以附件形式下载
// 4. 附件下载 attachment 附件 inline 在线打开(默认值)// 在线打开response.setHeader("content-disposition", inline + ";fileName=" + fileName);// 附件下载response.setHeader("content-disposition", attachment + ";fileName=" + fileName);
设置文件下载为在线打开的形式时,如果是浏览器可以打开的类型,比如 txt、png等类型,会直接打开,但是如果是exe等浏览器不能打开的类型时,它会尝试去用自己可以打开的类型(txt、png等)去打开,但是如果还是打不开,它就会以附件下载的形式下载下来。
尝试打开 cc.exe、dd.exe、ee.exe,并设置打开方式为在线打开
@Controller@RequestMapping("file")public class FileController { // 用来处理文件下载 请求对应响应输出流 @RequestMapping("download") public void download(String openStyle, String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException { openStyle = openStyle == null ? "inline" : "attachment"; System.out.println("下载文件的名称:" + fileName); // 1. 根据下载相对目录获取下载目录在服务器部署之后绝对目录 String realPath = request.getSession().getServletContext().getRealPath("/down"); // 2. 通过文件输入流读取文件 FileInputStream is = new FileInputStream(new File(realPath, fileName)); // 3. 获取响应输出流 response.setContentType("text/plain;charset=UTF-8"); // 4. 附件下载 attachment 附件 inline 在线打开(默认值) response.setHeader("content-disposition", "inline" + ";fileName=" + URLEncoder.encode(fileName, "UTF-8")); // response.setHeader("content-disposition", openStyle + ";fileName=" + fileName); ServletOutputStream os = response.getOutputStream(); // 5. 处理下载流复制// 操作io流用IOUtils 操作file用FileUtils // 通过工具类处理下载里复制和关闭流 IOUtils.copy(is, os); IOUtils.closeQuietly(is); // 优雅关闭 安静关流 IOUtils.closeQuietly(os); // 优雅关闭 安静关流 // 传统写法 /* int len; byte[] b = new byte[1024]; while(true){ len = is.read(b); if(len == -1) break; os.write(b, 0, len); } // 释放资源 os.close(); is.close();*/ }}
- 一般我们在网页进行下载的时候,都会提供两种形式,一种是在线打开,一种是附件下载
upload.jsp中文件下载:
<h1>文件下载</h1><ul> <li>aa.txt <a href="${pageContext.request.contextPath}/file/download?fileName=aa.txt">在线打开</a> <a href="${pageContext.request.contextPath}/file/download?fileName=aa.txt&openStyle=attch">附件下载</a> </li> <li>cc.exe <a href="${pageContext.request.contextPath}/file/download?fileName=cc.exe">在线打开</a> <a href="${pageContext.request.contextPath}/file/download?fileName=cc.exe&openStyle=attch">附件下载</a> </li> <li>dd.exe <a href="${pageContext.request.contextPath}/file/download?fileName=dd.exe">在线打开</a> <a href="${pageContext.request.contextPath}/file/download?fileName=dd.exe&openStyle=attch">附件下载</a> </li></ul>
@Controller@RequestMapping("file")public class FileController { // 用来处理文件下载 请求对应响应输出流 @RequestMapping("download") public void download(String openStyle, String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException { openStyle = openStyle == null ? "inline" : "attachment"; System.out.println("下载文件的名称:" + fileName); // 1. 根据下载相对目录获取下载目录在服务器部署之后绝对目录 String realPath = request.getSession().getServletContext().getRealPath("/down"); // 2. 通过文件输入流读取文件 FileInputStream is = new FileInputStream(new File(realPath, fileName)); // 3. 获取响应输出流 response.setContentType("text/plain;charset=UTF-8"); // 4. 附件下载 attachment 附件 inline 在线打开(默认值) //response.setHeader("content-disposition", "inline" + ";fileName=" + URLEncoder.encode(fileName, "UTF-8")); response.setHeader("content-disposition", openStyle + ";fileName=" + fileName); ServletOutputStream os = response.getOutputStream(); // 5. 处理下载流复制// 操作io流用IOUtils 操作file用FileUtils // 通过工具类处理下载里复制和关闭流 IOUtils.copy(is, os); IOUtils.closeQuietly(is); // 优雅关闭 安静关流 IOUtils.closeQuietly(os); // 优雅关闭 安静关流 // 传统写法 /* int len; byte[] b = new byte[1024]; while(true){ len = is.read(b); if(len == -1) break; os.write(b, 0, len); } // 释放资源 os.close(); is.close();*/ }}
- 在处理下载流复制和关闭流时我们可以使用工具类去简化代码
// 5. 处理下载流复制// 操作io流用IOUtils 操作file用FileUtils// 通过工具类处理下载流复制和关闭流IOUtils.copy(is, os);IOUtils.closeQuietly(is); // 优雅关闭 安静关流IOUtils.closeQuietly(os); // 优雅关闭 安静关流// 传统写法/*int len;byte[] b = new byte[1024];while(true){ len = is.read(b); if(len == -1) break; os.write(b, 0, len);}// 释放资源os.close();is.close();*/
- 如果文件名有中文,需要主动进行编码处理
response.setHeader("content-disposition", "inline" + ";fileName=" + URLEncoder.encode(fileName, "UTF-8"));
总结: