开门见山,我们直接来看jsp代码:
这是一个form表单,enctype中的值和用别的组件或流上传时的值是一样的都是:multipart/form-data. 还有就是method值必须为post。file表单我就不再多说,都懂得。<form action="/upload/upload" enctype="multipart/form-data" method="post"> <input type="file" name="filename" /><br> <input type="submit" value="上传"/><br> </form> ${msg }
因为在表单实现上传时,servlet中的request得到传输值得方法已经不能用了(作废),但是request还可以设置字符编码,因为在commons组件中它自己会调用这个方法request.setCharacterEncoding("utf-8"); request设置字符编码的方法有两种,上面是第一种,第二种是servletFileUpload.setHeaderEncoding("utf-8");这种优先级高于上一种,通常使用第一种。import java.io.File; import java.io.IOException; import java.util.List; 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; import cn.itcast.commons.CommonUtils; public class upload extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); //得到工厂 DiskFileItemFactory factory = new DiskFileItemFactory(10*1024,new File("F:/temp")); //得到解析器 ServletFileUpload sfu = new ServletFileUpload(factory); try { //限制文件的大小,必须在解析得到List之前调用,否则限制无效 //sfu.setFileSizeMax(100); //解析得到List List<FileItem> list = sfu.parseRequest(request); //得到表单项 FileItem fl = list.get(0); /** * 1.得到文本保存的路径 */ String root = this.getServletContext().getRealPath("/WEB-INF/files/"); /** * 2.生成二层目录 * 1) 得到文件名称 * 2) 得到hashcode * 3) 转化成16进制 * 4) 获取前两个字符来生成目录 */ String filename = fl.getName(); //处理文件名的绝对路径问题 int index = filename.lastIndexOf("\\"); if(index != -1) { filename = filename.substring(index+1); } //给文件名添加uuid前缀,处理文件同名问题 String savename = CommonUtils.uuid() + "_" +filename; //得到hashcode int hCode = savename.hashCode(); String hex = Integer.toHexString(hCode); //获取hex的前两个字母,与root连接在一起,生成一个完整的路径 File dirFile = new File(root ,hex.charAt(0)+"\\" +hex.charAt(1) ); //创建目录链 dirFile.mkdirs(); //创建目录文件 File destFile = new File(dirFile,savename); //保存 fl.write(destFile); } catch (Exception e) { if(e instanceof FileUploadBase.FileSizeLimitExceededException) { request.setAttribute("msg", "您上传的文件超出了100K."); request.getRequestDispatcher("index.jsp").forward(request, response); } } } }
这是用httpwatch捕获到的文件上传时提交的代码,下面来分析一下这段代码:POST /upload/upload HTTP/1.1 Accept: text/html, application/xhtml+xml, */* X-HttpWatch-RID: 14415-10046 Referer: http://localhost:8080/upload/ Accept-Language: zh-CN User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko Content-Type: multipart/form-data; boundary=---------------------------7df13a1920408 Accept-Encoding: gzip, deflate Host: localhost:8080 Content-Length: 733114 DNT: 1 Connection: Keep-Alive Cache-Control: no-cache Cookie: JSESSIONID=100387FBC7C815A0A951F1ABE69D7D26 -----------------------------7df13a1920408 Content-Disposition: form-data; name="filename"; filename="struts灏忛」鐩?zip" Content-Type: application/x-zip-compressed
* 1.得到文本保存的路径
*/
String root = this.getServletContext().getRealPath("/WEB-INF/files/");
上面的代码是得到文件上传的根路径,完成文件上传前,必须在WEB-INF目录下创建一个files文件夹,表示把所有上传的文件都放在该文件夹中,这样别人就不能访问你的资源。
* 2.生成二层目录
* 1) 得到文件名称
* 2) 得到hashcode
* 3) 转化成16进制
* 4) 获取前两个字符来生成目录
*/
String filename = fl.getName();
//处理文件名的绝对路径问题
int index = filename.lastIndexOf("\\");
if(index != -1)
{
filename = filename.substring(index+1);
}
//给文件名添加uuid前缀,处理文件同名问题
String savename = CommonUtils.uuid() + "_" +filename;
//得到hashcode
int hCode = savename.hashCode();
String hex = Integer.toHexString(hCode);
//获取hex的前两个字母,与root连接在一起,生成一个完整的路径
File dirFile = new File(root ,hex.charAt(0)+"\\" +hex.charAt(1) );
//创建目录链
dirFile.mkdirs();
//创建目录文件
File destFile = new File(dirFile,savename);
//保存
fl.write(destFile);