|
@@ -0,0 +1,74 @@
|
|
|
+package com.lovecoding.download;
|
|
|
+
|
|
|
+import org.apache.commons.io.IOUtils;
|
|
|
+
|
|
|
+import javax.servlet.ServletOutputStream;
|
|
|
+import javax.servlet.annotation.WebServlet;
|
|
|
+import javax.servlet.http.HttpServlet;
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileInputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.net.URLEncoder;
|
|
|
+
|
|
|
+@WebServlet("/downloadFile")
|
|
|
+public class DownloadAction extends HttpServlet {
|
|
|
+
|
|
|
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 正常的情况下 , 下载是不走Java逻辑代码的
|
|
|
+ * 我们下载文件都交给 Tomcat, 文件是静态资源, Http 服务器 (Tomcat, Nginx ) 都能处理
|
|
|
+ * 我们不用管 文件下载的事情
|
|
|
+ * 特俗情况, 付费下载, 统计文件下载数量, 管控下载流量
|
|
|
+ */
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 一般情况下, 管控文件下载需要 Token !
|
|
|
+ * 我们改需要 文件名
|
|
|
+ * 我们使用 Java 管控文件下载 不一定非要 使用Java IO去处理文件
|
|
|
+ * 301 跳转
|
|
|
+ */
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 一般情况下 我们需要把文件重命名, 或者加随即时间戳
|
|
|
+ * 总之呢 尽可能不让用户猜到文件路径, 方案有很多
|
|
|
+ * 用户使用的是一个映射文件名 "abc.pdf" => "202030517-abc.pdf"
|
|
|
+ * 用户可能上传 攻击脚本
|
|
|
+ */
|
|
|
+
|
|
|
+ req.setCharacterEncoding("UTF-8");
|
|
|
+ String fileName = req.getParameter("filename");
|
|
|
+
|
|
|
+ if ( fileName == null || fileName.equals("") ) {
|
|
|
+ resp.setContentType("text/html; charset=utf-8");
|
|
|
+ resp.getWriter().print("请携带文件名访问");
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+ //取存储文件的文件夹路径
|
|
|
+ String filePath = req.getServletContext().getRealPath("") + "uploads";
|
|
|
+ //取拼接文件名
|
|
|
+ String file = filePath + File.separator + fileName;
|
|
|
+ //判断文件是否存在
|
|
|
+ File file1 = new File(file);
|
|
|
+ if ( !file1.exists() ) {
|
|
|
+ resp.setContentType("text/html; charset=utf-8");
|
|
|
+ resp.getWriter().print("<h1>文件不存在</h1>");
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+ //文件转文件流
|
|
|
+ FileInputStream fileInputStream = new FileInputStream(file1);
|
|
|
+ //取相应流
|
|
|
+ ServletOutputStream outputStream = resp.getOutputStream();
|
|
|
+ //向浏览器声明下载
|
|
|
+ resp.addHeader("content-type", "application/octet-stream");
|
|
|
+ //声明文件名
|
|
|
+ String downloadFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
|
|
|
+ resp.addHeader("content-disposition", "attachment; filename*=UTF-8''" + downloadFileName);
|
|
|
+ //将文件的文件流和resp相应流合并输出
|
|
|
+ IOUtils.copy( fileInputStream, outputStream );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|