同样,其中涉及到的jar包
在这里我为文件上传的时候,添加了描述,希望文件上传的时候,也附带一些文字信息;
info的内容为空:null;
回忆到为了上传文件,我把表单的格式(entype)修改成了:
enctype="multipart/form-data"
这种情况下的内容必须通过POST方式这是第一点;
其次内容的格式是:
------------------121211212
Content-Disposition: form-data; name="attachment01"; filename="aaa.txt"
Content-Type: text/plain
hello world
------------------121211212
Content-Disposition: form-data; name="attachment02"; filename="bbb.txt"
Content-Type: text/plain
xxxx
dfhuhfhdsu
------------------121211212--
之前默认的是:
enctype="application/x-www-form-urlencoded"
可以通过POST传值,和GET的URL传值(http://dssss?name=mzy&&password=123456):
其中的格式解析了都是:
attachement01=aaa.txt&&attachement02=bbb.txt
格式都不同了,所以不能再使用简单的,request.getParameter了!
在开发模式下查看此刻的info的格式为:
我发现其实普通的表单字段也是封装在List<FileItem>中的
每一个input,不管是文件还是普通字段,都是一个item对象。
所以可以通过组件中的ifFormField方法进行是否是简单窗体字段的判断(是否是文件)
然后通过其中的getString方法,去得到其中的内容;
getString方法可以传参,传编码格式:
具体如:getString("utf-8");
没设置getString的编码的时候:
设置utf-8之后:
下面贴代码了:
JSP中:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>文件上传</title> </head> <body> <font color="red">${msg }</font> <form action="${pageContext.servletContext.contextPath }/servlet/UpLoadDemo05" method="POST" enctype="multipart/form-data"> 请选择要上传的文件一:<input type="file" name="attachment01" />描述一:<input type="text" name="info1"/><br/> 请选择要上传的文件二:<input type="file" name="attachment02" />描述二:<input type="text" name="info2"/><br/> <!-- 请选择要上传的文件三:<input type="file" name="attachment03" /><br/> --> <input type="submit" value="上传文件"/> </form> </body> </html>
servlet中:
package upload; import java.io.File; import java.io.IOException; 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.FileSizeLimitExceededException; import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException; import org.apache.commons.fileupload.ProgressListener; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FileUtils; import exception.FileTypeErrorException; /** * 文件上传!细节注意: * 1.限制单文件的大小 * 2.限制总文件的大小 * 3.限制文件的类型 * 4.解决之前的文件同名覆盖的问题 * 5.在file下生成有规律有意义,可查找或者安全的目录。 * * 6.增加描述!!! * * 使用apache的文件上传和下载的组件 * 1.导入jar包 * commons-fileload-1.2.2.jar * commons-io-2.1.jar 一个IO流工具(更方便) * @author mzy */ public class UpLoadDemo05 extends HttpServlet { private static final long serialVersionUID = 987003232758385500L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { DiskFileItemFactory factory = new DiskFileItemFactory(10*1024, new File("e:/temp")); ServletFileUpload upload = new ServletFileUpload(factory); /* * 注册一个文件监听器: * 监听上传的进度! */ // upload.setProgressListener(new MyProgressListener()); upload.setHeaderEncoding("utf-8"); /* * 注意限制文件大小的两个方法: * setFileSizeMax(100*1024):单个文件大小不超过100KB * setSizeMax(300*1024):文件总大小不超过300KB */ // 一个request中最大的容量为300KB upload.setSizeMax(300*1024); // 单个文件的最大容量为100KB upload.setFileSizeMax(100*1024); // 解析request List<FileItem> list = upload.parseRequest(request); if(list != null) { // String info1 = request.getParameter("info1"); // System.out.println("info1"+info1); for(FileItem item: list) { /* * 确定文件项实例是否表示简单窗体字段。 * 如果实例表示简单表单字段,则返回true; * 如果它表示已上传文件,则为false。 */ if(item.isFormField()) { // 除文件外的其它表单组件 if(item.getFieldName().equals("info1")) { String info1 = item.getString("utf-8"); System.out.println("info1 = "+info1); } if(item.getFieldName().equals("info2")) { String info2 = item.getString("utf-8"); System.out.println("info2 = "+info2); } } else { /* * 注意: * 限制文件的类型。文件的 * 类型(mime-type):image/* * 只能上传图片 */ // 得到文件的类型 String contentType = item.getContentType(); if(!contentType.contains("image/")) { throw new FileTypeErrorException("文件类型错误,请换一张图片!"); } /* * 使用UUID算法,生成唯一的文件名 * 避免文件覆盖的问题! */ String uuid = UUID.randomUUID().toString(); // get到真正的文件名! /* * 这里我们就不用做兼容性的处理了 * 因我们只用get一个LastIndexOf(".") * 去获得文件的后缀名,保证文件能够正常的打开! */ String fileName = item.getName(); // 获取到后缀名 fileName = fileName.substring(fileName.lastIndexOf(".")); // 组合新的文件名 String newFileName = uuid+fileName; // 得到新的目录结构 String dir = "e:/files/"+makeDirectory(newFileName); // 生成目录结构 File file = new File(dir); // 如果不存在这个目录结构! if(!file.exists()) { file.mkdirs(); // mkdir只能生成单个目录,所以要用mkdirs } //开始文件传输 FileUtils.copyInputStreamToFile(item.getInputStream(), new File(dir+newFileName)); // 删除item传输的tmp临时文件 item.delete(); } } } } catch (FileTypeErrorException e) { // 捕获文件类型异常 request.setAttribute("msg", e.getMessage()); request.getRequestDispatcher("/04.upload.jsp").forward(request, response); } catch (FileSizeLimitExceededException e) { // 捕获单个文件大小超规定范围异常 request.setAttribute("msg", "单个文件超过设定大小:100KB"); request.getRequestDispatcher("/04.upload.jsp").forward(request, response); } catch (SizeLimitExceededException e) { // 捕获总文件大小超规定范围异常 request.setAttribute("msg", "总文件超过设定大小:300KB"); request.getRequestDispatcher("/04.upload.jsp").forward(request, response); } catch (Exception e) { e.printStackTrace(); } } /** * 思考,生成有意义的目录结构: * * 第一种三层结构: 年-月-日 * * * 第二种两层结构:通过hashcode生成的更安全的随机目录 * 动态生成新的目录结构: * (第一级目录)/(第二级目录) * @return 新的目录结构:右边是带斜杠的(左边不带), * 可直接进行字符串拼接 */ private String makeDirectory(String fileName) { // 1.得到文件名的hashCode int code = fileName.hashCode(); // 2.算出第一层目录的名称 // 第一层目录的数字大小不会超过15 int first = code & 0xF; // 十六进制的15 // 3.算出第二层目录的名称:先右移一位 int second = code & (0xF >> 1); return first+"/"+second+"/"; } /** * 实现ProgressListener监听文件上传进度 */ class MyProgressListener implements ProgressListener { /* * 参数1:目前上传了多少字节 * 参数2:总长度 * 参数3:目前正在第几个文件 */ @Override public void update(long pBytesRead, long pContentLength, int pItems) { System.out.println("正在上传第"+pItems+"个文件!"); System.out.println("已经上传了"+pBytesRead+"字节"+",总字节为"+pContentLength+"字节"); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); doGet(request, response); } }