DownloadAction.java 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package com.lovecoding.download;
  2. import org.apache.commons.io.IOUtils;
  3. import javax.servlet.ServletOutputStream;
  4. import javax.servlet.annotation.WebServlet;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8. import java.io.File;
  9. import java.io.FileInputStream;
  10. import java.io.IOException;
  11. import java.net.URLEncoder;
  12. @WebServlet("/downloadFile")
  13. public class DownloadAction extends HttpServlet {
  14. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
  15. /**
  16. * 正常的情况下 , 下载是不走Java逻辑代码的
  17. * 我们下载文件都交给 Tomcat, 文件是静态资源, Http 服务器 (Tomcat, Nginx ) 都能处理
  18. * 我们不用管 文件下载的事情
  19. * 特俗情况, 付费下载, 统计文件下载数量, 管控下载流量
  20. */
  21. /**
  22. * 一般情况下, 管控文件下载需要 Token !
  23. * 我们改需要 文件名
  24. * 我们使用 Java 管控文件下载 不一定非要 使用Java IO去处理文件
  25. * 301 跳转
  26. */
  27. /**
  28. * 一般情况下 我们需要把文件重命名, 或者加随即时间戳
  29. * 总之呢 尽可能不让用户猜到文件路径, 方案有很多
  30. * 用户使用的是一个映射文件名 "abc.pdf" => "202030517-abc.pdf"
  31. * 用户可能上传 攻击脚本
  32. */
  33. req.setCharacterEncoding("UTF-8");
  34. String fileName = req.getParameter("filename");
  35. if ( fileName == null || fileName.equals("") ) {
  36. resp.setContentType("text/html; charset=utf-8");
  37. resp.getWriter().print("请携带文件名访问");
  38. return ;
  39. }
  40. //取存储文件的文件夹路径
  41. String filePath = req.getServletContext().getRealPath("") + "uploads";
  42. //取拼接文件名
  43. String file = filePath + File.separator + fileName;
  44. //判断文件是否存在
  45. File file1 = new File(file);
  46. if ( !file1.exists() ) {
  47. resp.setContentType("text/html; charset=utf-8");
  48. resp.getWriter().print("<h1>文件不存在</h1>");
  49. return ;
  50. }
  51. //文件转文件流
  52. FileInputStream fileInputStream = new FileInputStream(file1);
  53. //取相应流
  54. ServletOutputStream outputStream = resp.getOutputStream();
  55. //向浏览器声明下载
  56. resp.addHeader("content-type", "application/octet-stream");
  57. //声明文件名
  58. String downloadFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
  59. //header 使用 filename*=UTF-8'' 协议告诉浏览器后台文件编码是 UTF-8 可以解决中文文件名乱码问题
  60. resp.addHeader("content-disposition", "attachment; filename*=UTF-8''" + downloadFileName);
  61. //将文件的文件流和resp相应流合并输出
  62. IOUtils.copy( fileInputStream, outputStream );
  63. }
  64. }