文件上传技术
Servlet3.0:注解开发,文件上传,异步请求。
JSPSmartUpload:嵌入到JSP中完成文件上传.主要用于Model1年代的。
FileUpload:Apache的文件上传组件。
Struts2:底层是FileUpload。
Servlet3.0
Servlet3.0与Servlet2.5提供了三个新特性:
注解开发:方便
文件上传:有些API不是特别全.
异步请求:
/** * 异步请求的Servlet */ @WebServlet(urlPatterns="/AsyncServlet",asyncSupported=true) public class AsyncServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { AsyncContext context = request.startAsync(request, response); context.start(new MyRunnable(context)); for(int i = 1;i<=10;i++){ System.out.println(i); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } class MyRunnable implements Runnable{ private AsyncContext context; public MyRunnable(AsyncContext context) { this.context = context; } @Override public void run() { for(char i='a';i<='z';i++){ try { context.getResponse().getWriter().println(i); Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } } } }
Servlet3.0的注解开发
@WebServlet
@WebListener
@WebFilter
文件上传的要素
表单的提交的方式必须是POST。
表单中需要有文件上传的表单元素:这个元素这个元素必须有name属性和值:<input type=”file” name=”upload”>。
表单的enctype属性的值必须是multipart/form-data。
文件上传问题解决
文件重名
使用UUID作为随机的文件名。
真实文件名和UUID存入数据表。
文件上传的目录分离
按时间分;
按数量分;
按用户分;
按目录分离算法分:
使用唯一文件名.hashCode(); -- 得到一个代表当前这个文件的int类型值。
int类型占4个字节32位.可以让hashCode值&0xf; 得到一个int值,用这个int值作为一级目录。
让hashCode右移4位 &0xf ;得到一个int值,用这个int值作为二级目录.依次类推。
代码实现
1:设置一个文件上传页面.
2:点击提交,提交到Servlet中.
没有设置enctype属性的时候:只能获得文件的名称,而没有文件内容.
设置enctype属性为multipart/form-data:获得到文件名及文件内容.
3:在Servlet中接收参数.
4:获得服务器的文件上传的路径.
5:通过流写到该路径下就OK了.
package com.boomoom.upload; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; import com.boomoom.utils.UUIDUtils; import com.boomoom.utils.UploadUtils; /** * 文件上传的Servlet */ @WebServlet("/UploadServlet") @MultipartConfig public class UploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 接收普通数据: request.setCharacterEncoding("UTF-8"); String filedesc = request.getParameter("filedesc"); System.out.println("文件描述"+filedesc); // 接收文件: Part part = request.getPart("upload"); long size = part.getSize();// 获得文件大小: System.out.println("文件大小:"+size); String name = part.getName(); System.out.println("文件表单中的name属性的名称"+name); // 获得文件名: String header = part.getHeader("Content-Disposition"); int idx = header.lastIndexOf("filename=""); String fileName = header.substring(idx+10, header.length()-1); System.out.println("文件名:"+fileName); // 获得文件内容: InputStream is = part.getInputStream(); // 获得upload的路径: String path = this.getServletContext().getRealPath("/upload"); // 获得文件的唯一文件名: String uuidFileName = UUIDUtils.getUUIDFileName(fileName); String realPath = path+UploadUtils.getPath(uuidFileName); File file = new File(realPath); if(!file.exists()){ file.mkdirs(); } OutputStream os = new FileOutputStream(realPath+"/"+uuidFileName); byte[] b = new byte[1024]; int len = 0; while((len = is.read(b))!=-1){ os.write(b, 0, len); } is.close(); os.close(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
package com.boomoom.utils; import java.util.UUID; public class UUIDUtils { public static String getUUID(){ return UUID.randomUUID().toString().replace("-", ""); } public static String getUUIDFileName(String fileName){ return UUID.randomUUID().toString().replace("-", "")+"_"+fileName; } }
package com.boomoom.utils; public class UploadUtils { public static String getPath(String uuidFileName){ // 使用唯一文件名.hashCode(); int code1 = uuidFileName.hashCode(); int d1 = code1 & 0xf; // 获得到1级目录. int code2 = code1 >>> 4; int d2 = code2 & 0xf; // 获得到2级目录. return "/"+d1+"/"+d2; } }