day20之用Servlet实现文件上传和下载(借助第三方开发包)
2014-03-19 21:56
477 查看
一、文件上传的必要前提:
1、表单的method必须是post的。
2、表单的enctype属性取值必须是multipart/form-data
enctype属性作用:指示请求消息正文内容的编码类型(MIME协议)
表单的enctype属性的默认值是application/x-www-form-urlencoded ( request.getParameter("username");)
正文:username=abc&password=123
表单的enctype属性取值为:multipart/form-data;boundary=---------------------------7de1f12d90da0(分隔符)
正文:多部分的表单数据组成的
-----------------------------7de1f12d90da0
Content-Disposition: form-data; name="username"
abc
-----------------------------7de1f12d90da0
Content-Disposition: form-data; name="photo"
123
-----------------------------7de1f12d90da0--
3、表单中提供input type="file"类型的上传输入域
二、借助于第三方上传开发包commons-fileupload来完成上传
1、ServletFileUpload(核心解析包)
2、DiskFileItemFactory
public void setSizeThreshold(int sizeThreshold) 设置内存缓冲区的大小,默认值为10K。当上传文件大于缓冲区大小时, fileupload组件将使用临时文件缓存上传文件。
public void setRepository(java.io.File repository) 设置临时文件存放的目录。指定临时文件目录,默认值为System.getProperty("java.io.tmpdir").
三、文件上传需要考虑的9个问题
1、保证服务器安全
把存放上传文件的目录放在WEB-INF下
2、上传同名文件被覆盖
文件改名:唯一的文件名
a.txt ---->UUID_a.txt
3、把上传的文件分散目录存储:防止同一个文件夹中的文件太多 防止文件太多,找起来麻烦,所以建立文件夹
方案一:按日期 ”一天产生一个文件夹,当天的文件夹就存放当天所有的文件“
查询files目录中有没有按照当前日期命名的文件夹,有直接用。没有创建一个。
方案二:文件名的hashCode打散存储目录 一个文件夹下最多十五个文件夹,但是文件夹下的文件是不定的
4、中文乱码问题
4.1普通字段的中文乱码问题
FileItem.getString(String charset);//取普通字段的值
4.2上传的文件是中文文件名的问题
request.setCharacterEncoding("UTF-8");
5、限制文件上传的类型(并不能严格的做到)
文件的扩展名+文件的MIME类型
6、临时文件的处理问题
超过缓存的文件上传,会产生临时文件,临时文件需要手工删除。
上传完毕后:FileItem.delete();
7、限制上传文件的大小
7.1限制单个文件的上传大小
sfu.setFileSizeMax(5 * 1024 * 1024);// 单个文件不能超过5M
超出大小:org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException
7.2多文件上传限制总大小
sfu.setSizeMax(7*1024*1024);//总上传文件的大小不能超过7M
FileUploadBase.SizeLimitExceededException
8、多文件上传,有空的情况
if(filename==null||"".equals(filename)){
continue;
}
9、显示上传进度条(AJAX)
服务器端计算上传文件的百分比即可。
给ServletFileUpload注册一个监听器即可
下载源码:
一、文件上传的必要前提:
1、表单的method必须是post的。
2、表单的enctype属性取值必须是multipart/form-data
enctype属性作用:指示请求消息正文内容的编码类型(MIME协议)
表单的enctype属性的默认值是application/x-www-form-urlencoded ( request.getParameter("username");)
正文:username=abc&password=123
表单的enctype属性取值为:multipart/form-data;boundary=---------------------------7de1f12d90da0(分隔符)
正文:多部分的表单数据组成的
-----------------------------7de1f12d90da0
Content-Disposition: form-data; name="username"
abc
-----------------------------7de1f12d90da0
Content-Disposition: form-data; name="photo"
123
-----------------------------7de1f12d90da0--
3、表单中提供input type="file"类型的上传输入域
二、借助于第三方上传开发包commons-fileupload来完成上传
1、ServletFileUpload(核心解析包)
2、DiskFileItemFactory
public void setSizeThreshold(int sizeThreshold) 设置内存缓冲区的大小,默认值为10K。当上传文件大于缓冲区大小时, fileupload组件将使用临时文件缓存上传文件。
public void setRepository(java.io.File repository) 设置临时文件存放的目录。指定临时文件目录,默认值为System.getProperty("java.io.tmpdir").
三、文件上传需要考虑的9个问题
1、保证服务器安全
把存放上传文件的目录放在WEB-INF下
2、上传同名文件被覆盖
文件改名:唯一的文件名
a.txt ---->UUID_a.txt
3、把上传的文件分散目录存储:防止同一个文件夹中的文件太多 防止文件太多,找起来麻烦,所以建立文件夹
方案一:按日期 ”一天产生一个文件夹,当天的文件夹就存放当天所有的文件“
查询files目录中有没有按照当前日期命名的文件夹,有直接用。没有创建一个。
方案二:文件名的hashCode打散存储目录 一个文件夹下最多十五个文件夹,但是文件夹下的文件是不定的
4、中文乱码问题
4.1普通字段的中文乱码问题
FileItem.getString(String charset);//取普通字段的值
4.2上传的文件是中文文件名的问题
request.setCharacterEncoding("UTF-8");
5、限制文件上传的类型(并不能严格的做到)
文件的扩展名+文件的MIME类型
6、临时文件的处理问题
超过缓存的文件上传,会产生临时文件,临时文件需要手工删除。
上传完毕后:FileItem.delete();
7、限制上传文件的大小
7.1限制单个文件的上传大小
sfu.setFileSizeMax(5 * 1024 * 1024);// 单个文件不能超过5M
超出大小:org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException
7.2多文件上传限制总大小
sfu.setSizeMax(7*1024*1024);//总上传文件的大小不能超过7M
FileUploadBase.SizeLimitExceededException
8、多文件上传,有空的情况
if(filename==null||"".equals(filename)){
continue;
}
9、显示上传进度条(AJAX)
服务器端计算上传文件的百分比即可。
给ServletFileUpload注册一个监听器即可
<%@ page import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>文件上传</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="${pageContext.request.contextPath}/servlet/ServletDemo3" method="post" enctype="multipart/form-data"> username:<input type="text" name="username"/><br/> photo:<input type="file" name="photo"/><br/> <input type="submit" value="上传"/> </form> </body> </html>
package com.jxnu.servlet; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadBase; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; public class ServletDemo3 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8");//防止上传中文文件乱码 response.setContentType("text/html;charset=UTF-8"); String storeDir = getServletContext().getRealPath("/WEB-INF/files"); // 得到核心的请求正文解析器 DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();// 用默认缓存大小10K,使用默认的临时文件存放目录 fileItemFactory.setRepository(new File("d:/temp")); ServletFileUpload sfu = new ServletFileUpload(fileItemFactory); sfu.setFileSizeMax(5 * 1024 * 1024);// 单个文件不能超过5M // sfu.setSizeMax(7*1024*1024);//总上传文件的大小不能超过7M // 解析请求对象 try { List<FileItem> items = sfu.parseRequest(request); // 遍历:判断 for (FileItem item : items) { //每一个item表示一个表单输入项,包含普通表单字段和file字段,做不同处理 if (item.isFormField()) { // 普通表单字段:打印出来 String fieldName = item.getFieldName();// 字段名 String fieldValue = item.getString("UTF-8");// 字段值 按指定编码返回字段的值 防止表单输入中文乱码 System.out.println(fieldName + "=" + fieldValue); } else { // 上传的文件名 String filename = item.getName();// C:\Users\wzhting\Desktop\a.txt if(filename==null||"".equals(filename)){ continue; } // a.txt String mimeType = item.getContentType();// 获取上传文件的MIME类型 // 稍微靠谱(根据浏览器不同而不同) // System.out.println(mimeType); if (mimeType.startsWith("image/")) { // 文件上传字段:上传 InputStream in = item.getInputStream(); // 得文件的MIME类型 // String mimeType = // getServletContext().getMimeType(filename); // System.out.println(mimeType);// image/jpeg // 根据文件名的扩展名从Tomcat\conf\web.xml中查的 filename = filename .substring(filename.lastIndexOf("\\") + 1);// 截一下文件名 // 使文件名保持唯一 filename = UUID.randomUUID().toString() + "_" + filename; System.out.println(request.getRemoteAddr()+":"+filename); String childDir = makeDir(storeDir, filename);// 返回的是2014-03-17 // 普通的IO操作 OutputStream out = new FileOutputStream(storeDir + "\\" + childDir + "\\" + filename); int len = -1; byte b[] = new byte[1024]; while ((len = in.read(b)) != -1) { out.write(b, 0, len); } in.close(); out.close(); item.delete();// 删除临时文件 // } else { // response.getWriter().write("only jpeg is allowed"); } } } response.getWriter().write("upload success!"); } catch (FileUploadBase.FileSizeLimitExceededException e) { response.getWriter().write("单个文件大小不能超过5M!"); }catch(FileUploadBase.SizeLimitExceededException e){ response.getWriter().write("总文件大小不能超过7M!"); } catch (FileUploadException e) { e.printStackTrace(); } } /* * 一个文件夹下最多十五个文件夹,但是文件夹下的文件是不定的 总共文件夹是15*15个 * hashCode是int,32的二进制 1001 1100 0101 0000 1010 1101 0101 1101 0000 0000 * 0000 0000 0000 0000 0000 1111 &0xf * ----------------------------------------- 0000 0000 0000 0000 0000 0000 * 0000 1101: 0000~1111 0~15 16个整数 * * * 1001 1100 0101 0000 1010 1101 0101 1101 0000 0000 0000 0000 0000 0000 * 1111 0000 &0xf0 ----------------------------------------- 0000 0000 0000 * 0000 0000 0000 0101 0000 >>4 ----------------------------------------- * 0000 0000 0000 0000 0000 0000 0000 0101 :0000~1111 0~15 16个整数 */ // 按照UUID文件名的hashCode计算一个存储目录 private String makeDir(String storeDir, String filename) { int hashCode = filename.hashCode(); int dir1 = hashCode & 0xf;// 一级目录 int dir2 = (hashCode & 0xf0) >> 4;// 二级目录 String dir = "" + dir1 + "\\" + dir2; File f = new File(storeDir, dir); if (!f.exists()) { f.mkdirs(); } return dir; } // 按照当前日期创建子文件夹 ”一天产生一个文件夹,当天的文件夹就存放当天所有的文件“ private String makeDir(String storeDir) { Date now = new Date(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); String dir = df.format(now); File f = new File(storeDir, dir);// c:\apache\day20\WEB-INF\files\2014-03-17 if (!f.exists()) { f.mkdirs(); } return dir; } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
下载源码:
package com.jxnu.servlet; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //查询出所有的可下载的文件 public class listFilesServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //key:UUID文件名(下载用) value:老文件名(显示到页面上) Map<String, String> map = new HashMap<String, String>();//key:7308d0bc-479c-4166-bc16-7cfcb2cced38_蓝色风景.png value:蓝色风景.png //获取保存上传文件的files的真实路径 String storeDir = getServletContext().getRealPath("/WEB-INF/files"); File file = new File(storeDir); treeWalk(file,map);// request.setAttribute("map", map); request.getRequestDispatcher("/listFiles.jsp").forward(request, response); } //递归遍历:找到文件,把名称存到map中 private void treeWalk(File file, Map<String, String> map) { if(file.isDirectory()){ File files[] = file.listFiles();//获取所有的子文件夹或文件 for(File f:files) treeWalk(f, map); }else{ String uuidFileName = file.getName();//UUID文件名 String oldFileName = uuidFileName.substring(uuidFileName.indexOf("_")+1); map.put(uuidFileName, oldFileName); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
<%@ page import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>文件列表</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <c:forEach items="${map}" var="me"> <c:url value="/servlet/DownloadServlet" var="url"> <c:param name="filename" value="${me.key}"></c:param> </c:url> ${me.value} <a href="${url}">下载</a><br/> </c:forEach> </body> </html>
package com.jxnu.servlet; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //查询出所有的可下载的文件 public class listFilesServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //key:UUID文件名(下载用) value:老文件名(显示到页面上) Map<String, String> map = new HashMap<String, String>();//key:7308d0bc-479c-4166-bc16-7cfcb2cced38_蓝色风景.png value:蓝色风景.png //获取保存上传文件的files的真实路径 String storeDir = getServletContext().getRealPath("/WEB-INF/files"); File file = new File(storeDir); treeWalk(file,map);// request.setAttribute("map", map); request.getRequestDispatcher("/listFiles.jsp").forward(request, response); } //递归遍历:找到文件,把名称存到map中 private void treeWalk(File file, Map<String, String> map) { if(file.isDirectory()){ File files[] = file.listFiles();//获取所有的子文件夹或文件 for(File f:files) treeWalk(f, map); }else{ String uuidFileName = file.getName();//UUID文件名 String oldFileName = uuidFileName.substring(uuidFileName.indexOf("_")+1); map.put(uuidFileName, oldFileName); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
相关文章推荐
- Jsp+Servlet实现文件上传下载——前台页面开发
- 转载tangl_99的Servlet 实现文件上传下载--自己的一点心得
- 【ZT】Jsp/Servlet:实现文件上传与下载【二】
- iOS开发之结合asp.net webservice实现文件上传下载
- jsp+servlet+commons-fileupload-1.3.jar+commons-io-2.4.jar+jstl标签库实现文件上传与下载
- servlet实现文件上传下载
- 【ZT】Jsp/Servlet:实现文件上传与下载【三】
- Jsp/Servlet:实现文件上传与下载
- servlet实现文件上传和下载
- iOS开发之结合asp.net webservice实现文件上传下载
- Jsp/Servlet:实现文件上传与下载
- Servlet和Jsp实现原生的上传与下载文件
- Jsp+Servlet实现文件上传下载(一)--文件上传
- iOS开发之结合asp.net webservice实现文件上传下载
- Servlet和Jsp实现原生的上传与下载文件
- JSP+Servlet实现文件上传及下载案例
- servlet实现图片预览、文件上传下载(转载)
- Servlet实现文件上传下载
- Jsp/Servlet:实现文件上传与下载
- jsp+servlet实现文件的上传和下载