文件上传和下载

回顾

  1. 一、EL表达式
  2. Expression Lanauage 表达式语言
  3. 替代JSP页面中小脚本的
  4. <%=request.getAttribute("name")%> ===${name}
  5. 语法${名称}---->从小到大。pageContext——-->request-->session-->application
  6. 指定作用域查找${requestScope.name}
  7. ${1+1}
  8. 算术运算、逻辑运算、三目运算、关系运算
  9. empty null "" 是否为空字符串
  10. 隐式对象:
  11. pageContextrequestScopeSessionScopeApllicationScopepageScopeparamparamValuesheaderheaderValuescookieConfig
  12. 二、JSTL
  13. jstl standard
  14. <%@ taglib prefix = "c" uri="http://java.sun.com/jsp/jstl/core" %>
  15. <c:set var="" value="" scope></c:set>
  16. <c:out var="${}" ></c:out>
  17. <c:remove var=""></c:remove>
  18. <c:out var="${}" default="默认值" ></c:out>
  19. <c:if test="条件"></c:if>
  20. <c:choose>
  21. <c:when test=""></c:when>
  22. <c:when test=""></c:when>
  23. <c:when test=""></c:when>
  24. <c:otherwise>等价于else</c:otherwise>
  25. </c:choose>
  26. <c:forEach var="i" begin="1" end="100" step="1">
  27. 变量为 i 初始为1 100 每次增加1
  28. </c:forEach>
  29. <c:forEach items="${集合}" var="dept" varStatus="">
  30. ${dept.dname}
  31. </c:forEach>
  32. <select name="deptno">
  33. <c:forEach items="${allDept}" var="dept">
  34. <option value="${dept.deptno}"
  35. <c:if test="${emp.deptno==dept.deptno}">
  36. selected
  37. </c:if>
  38. >${dept.dname}</option>
  39. </c:forEach>
  40. </select>
  41. 三、MVC
  42. MODEL 实体类
  43. VIEW jsp
  44. CONTROLLER servlet
  45. web daoservice entity filter
  46. 四、分页
  47. limit

今日内容

  1. 1、文件上传
  2. 2、文件下载

教学目标

  1. 1、掌握文件上传
  2. 2、掌握文件下载

第一节 文件上传

1.1 文件上传三要素
  • 提供form表单,method必须是post!
  • form表单的enctype必须是multipart/form-data
  • 提供 input type=”file” 类型输入

1.2 实现文件上传

1.2.2 编写上传页面
  1. <%@ page language="java" pageEncoding="UTF-8"%>
  2. <!DOCTYPE HTML>
  3. <html>
  4. <head>
  5. <title>文件上传</title>
  6. </head>
  7. <body>
  8. <form action="${pageContext.request.contextPath}/servlet/UploadHandleServlet" enctype="multipart/form-data" method="post">
  9. 上传用户:<input type="text" name="username"><br/>
  10. 上传文件1:<input type="file" name="file1"><br/>
  11. 上传文件2:<input type="file" name="file2"><br/>
  12. <input type="submit" value="提交">
  13. </form>
  14. </body>
  15. </html>

1.2.3 配置
  1. <servlet>
  2. <servlet-name>UploadHandleServlet</servlet-name>
  3. <servlet-class>me.gacl.web.controller.UploadHandleServlet</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>UploadHandleServlet</servlet-name>
  7. <url-pattern>/servlet/UploadHandleServlet</url-pattern>
  8. </servlet-mapping>

1.3 文件上传细节注意

上述的代码虽然可以成功将文件上传到服务器上面的指定目录当中,但是文件上传功能有许多需要注意的小细节问题,以下列出的几点需要特别注意的

1、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。

  1. String filepath = request.getServletContext().getRealPath("/WEB-INF/upload");

2、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。

  1. public class UploadUtils{
  2. //使用UUID生成唯一标识码,拼接上图片的名称。
  3. public static String NewFileName(String filename){
  4. return UUID.randomUUID().toString().replaceAll("-","")+"_"+filename;
  5. }
  6. }

3、为防止一个目录下面出现太多文件,要使用hash算法打散存储。

  1. public static String NewFilePath(String basePath,String filename){
  2. int hashcode = filename.hashCode();
  3. int path1 = hashcode&15;//与运算 0~15 二级
  4. int path2 = (hashcode>>4)&15;//与运算 0~15 三级
  5. String dir = basePath+"\\"+path1+"\\"+path2;//与一级目录拼接一起
  6. File file = new File(dir);
  7. if(!file.exists()){
  8. file.mkdirs();
  9. }
  10. return dir;
  11. }

4、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。**

  1. //创建一个集合存放允许上传的文件的类型(后缀名)
  2. //判断所上传的文件在当前集合当中是否包含。
  3. List<String> nameList = new ArrayList<String>();
  4. nameList.add(".jpg");
  5. nameList.add(".bmp");
  6. nameList.add(".png");
  7. String extName = filename.substring(filename.lastIndexOf("."));
  8. if(!nameList.contains(extName)){
  9. System.out.println("上传失败");
  10. return;
  11. }

最终处理代码改进为:

  1. package com.qf.servlet;
  2. import java.io.IOException;
  3. import java.util.Collection;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.annotation.MultipartConfig;
  6. import javax.servlet.annotation.WebServlet;
  7. import javax.servlet.http.HttpServlet;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10. import javax.servlet.http.Part;
  11. import org.apache.commons.io.IOUtils;
  12. import com.qf.utils.FileUploadUtils;
  13. @WebServlet(value = "/upLoadfile2")
  14. @MultipartConfig(fileSizeThreshold=1024*100,maxFileSize=1024*1024*2,maxRequestSize=1024*1024*20)
  15. public class UploadFileServlet2 extends HttpServlet {
  16. private static final long serialVersionUID = 1L;
  17. public UploadFileServlet2() {
  18. super();
  19. }
  20. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  21. request.setCharacterEncoding("utf-8");
  22. response.setContentType("text/html;charset=utf-8");
  23. //得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
  24. String basepath=request.getServletContext().getRealPath("/WEB-INF/upload");
  25. File dir=new File(savepath);
  26. if(!dir.exists()){
  27. dir.mkdirs();
  28. }
  29. Collection<Part> parts = request.getParts();
  30. if(parts!=null) {
  31. for (Part part : parts) {
  32. //获取文件提交的名字
  33. String filename=part.getSubmittedFileName();
  34. if(filename!=null) {//文件
  35. if(filename.trim().equals("")) {
  36. continue;
  37. }
  38. System.out.println(filename);
  39. //获得包含UUID的文件名
  40. String newFilename=FileUploadUtils.getNewFileName(filename);
  41. //获取分散后的路径
  42. String newpath=FileUploadUtils.getNewPath(basepath, filename);
  43. //存储
  44. part.write(newpath+"\\"+newFilename);
  45. System.out.println(filename+"上传成功");
  46. response.getWriter().write(filename+"上传成功");
  47. part.delete();//删除缓存文件
  48. }else {//不是文件
  49. String name=part.getName();
  50. String value=request.getParameter(name);
  51. System.out.println(name+"...."+value);
  52. }
  53. }
  54. }
  55. }
  56. /**
  57. * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
  58. */
  59. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  60. // TODO Auto-generated method stub
  61. doGet(request, response);
  62. }
  63. }

第二节 文件下载

我们要将Web应用系统中的文件资源提供给用户进行下载,首先我们要有一个页面列出上传文件目录下的所有文件,当用户点击文件下载超链接时就进行下载操作,编写一个ListFileServlet,用于列出Web应用系统中所有下载文件

2.1 获取文件列表

工具类遍历目录方法

  1. public static void getFileList(File file, HashMap<String,String> filenames){
  2. //获取当前文件对象下的所有内容(文件、文件夹)
  3. File[] files = file.listFiles();
  4. //如果数组不为空,证明有文件、文件夹
  5. if(files!=null){
  6. //每次拿到文件对象(文件、文件夹 )
  7. for (File file1 : files) {
  8. if(file1.isDirectory()){
  9. getFileList(file1,filenames );
  10. }else{
  11. //获得文件的名称
  12. String filename = file1.getName();
  13. //获取第一个_的下标
  14. int i = filename.indexOf("_");
  15. //获取源文件名称(可能包含_)
  16. String realName= filename.substring(i + 1);
  17. //UUID键 源文件名 值
  18. filenames.put(filename, realName);
  19. }
  20. }
  21. }
  22. }
  1. package com.qf.web.servlet;
  2. import com.qf.utils.UpLoadUtils;
  3. import javax.servlet.ServletException;
  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.IOException;
  10. import java.util.HashMap;
  11. @WebServlet(name = "FileListServlet",value = "/filelist")
  12. public class FileListServlet extends HttpServlet {
  13. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  14. doGet(request, response);
  15. }
  16. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  17. //0乱码
  18. request.setCharacterEncoding("utf-8");//用户名的乱码
  19. response.setContentType("text/html;charset=utf-8");
  20. //1获取文件列表
  21. HashMap<String, String> filemap=new HashMap<>();
  22. String savepath=request.getServletContext().getRealPath("/WEB-INF/upload");
  23. UpLoadUtils.fileList(new File(savepath), filemap);
  24. //2转发
  25. request.setAttribute("map", filemap);
  26. request.getRequestDispatcher("/list.jsp").forward(request, response);
  27. }
  28. }

2.2 配置

在Web.xml文件中配置ListFileServlet

  1. <servlet>
  2. <servlet-name>ListFileServlet</servlet-name>
  3. <servlet-class>me.gacl.web.controller.ListFileServlet</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>ListFileServlet</servlet-name>
  7. <url-pattern>/servlet/ListFileServlet</url-pattern>
  8. </servlet-mapping>

2.3 下载页面

展示下载文件的listfile.jsp页面如下:

  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  3. <html>
  4. <head>
  5. <title>下载文件列表</title>
  6. </head>
  7. <body>
  8. <h2>下载文件列表</h2>
  9. <table>
  10. <tr>
  11. <th>文件名</th>
  12. <th>操作</th>
  13. </tr>
  14. <c:forEach items="${map}" var="entry">
  15. <tr>
  16. <td>
  17. ${entry.value}
  18. </td>
  19. <td>
  20. <a href="${pageContext.request.contextPath}/down?filename=${entry.key}">下载</a>
  21. </td>
  22. </tr>
  23. </c:forEach>
  24. </table>
  25. </body>
  26. </html>

2.4 实现文件下载

编写一个用于处理文件下载的Servlet,DownLoadServlet的代码如下:

  1. package com.qf.web.servlet;
  2. import com.qf.utils.UpLoadUtils;
  3. import javax.servlet.ServletException;
  4. import javax.servlet.ServletOutputStream;
  5. import javax.servlet.annotation.WebServlet;
  6. import javax.servlet.http.HttpServlet;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import java.io.FileInputStream;
  10. import java.io.IOException;
  11. import java.net.URLEncoder;
  12. @WebServlet(name = "DownServlet",value ="/down")
  13. public class DownServlet extends HttpServlet {
  14. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  15. doGet(request, response);
  16. }
  17. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  18. request.setCharacterEncoding("utf-8");//用户名的乱码
  19. response.setContentType("text/html;charset=utf-8");
  20. //设置响应头
  21. String savepath=request.getServletContext().getRealPath("/WEB-INF/upload");
  22. //1获取文件名
  23. String uuidfilename = request.getParameter("filename");
  24. //拿到UUID的名字拆分。_之后的是原文件名
  25. String filename=uuidfilename.split("_")[1];
  26. //通过原文件名得到分散后的路径就是要下载的路径
  27. String realpath=UpLoadUtils.createNewPath(savepath, filename);
  28. //告诉浏览器如何处理流,当成文件保存
  29. response.setHeader("content-disposition", "attachment;filename="+ URLEncoder.encode(filename,"utf-8" ));
  30. //2使用流读取
  31. FileInputStream fis=new FileInputStream(realpath+"/"+uuidfilename);
  32. ServletOutputStream os = response.getOutputStream();
  33. byte[] buf=new byte[1024*4];
  34. int len=0;
  35. while((len=fis.read(buf))!=-1){
  36. os.write(buf,0,len);
  37. }
  38. //3关闭
  39. os.close();
  40. fis.close();
  41. }
  42. }

总结

文件上传步骤:

文件下载步骤:

作业题

  1. 1、完善图书图片的上传和下载功能

面试题

  1. 1、文件上传的页面表单必须要设置那些属性

image.png