本帖最后由 我是楠楠 于 2018-7-4 17:26 编辑
【郑州校区】使用Servlet3.0完成一个文件上传的功能
1.1.1 需求:在网站上有商品维护,上传商品图片,需要使用文件上传: 1.1.2 分析:1.1.2.1 技术分析:【文件上传的概述】 Ø 文件上传: * 指的是将本地的文件 写到 服务器上. Ø 文件上传技术: * Servlet3.0 :注解开发,文件上传,异步请求. * JSPSmartUpload :嵌入到JSP中完成文件上传.主要用于Model1年代的. * FileUpload :Apache的文件上传组件. * Struts2 :底层是FileUpload. Ø 文件上传的要素: * 表单的提交的方式必须是POST. * 表单中需要有文件上传的表单元素:这个元素这个元素必须有name属性和值:<input type=”file” name=”upload”> * 表单的enctype属性的值必须是multipart/form-data. 【Servlet3.0】 Ø Servlet3.0与Servlet2.5提供了三个新特性: * 注解开发 :方便 * 文件上传 :有些API不是特别全. * 异步请求 : 【Servlet3.0的注解开发】 Ø @WebServlet Ø @WebListener Ø @WebFilter 【文件上传原理分析】 Ø 设计文件上传的页面: 进行文件上传的抓包分析: 没有设置enctype属性的时候:只能获得文件的名称,而没有文件内容. 设置enctype属性为multipart/form-data:获得到文件名及文件内容. 1.1.3 代码实现:【步骤一】:设置一个文件上传页面. 【步骤二】:点击提交,提交到Servlet中. 【步骤三】:在Servlet中接收参数. 【步骤四】:获得服务器的文件上传的路径. 【步骤五】:通过流写到该路径下就OK了. 代码: [AppleScript] 纯文本查看 复制代码 @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");
OutputStream os = new FileOutputStream(path+"/"+fileName);
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);
}
} 1.1.4 总结:1.1.4.1 文件上传问题:文件名重名.使用随机的唯一文件名: * 使用UUID作为随机的文件名. 1.1.4.2 文件上传问题:一个目录下存放的文件过多.一个目录下文件过多,导致打开都很慢,更别说是读写操作. 目录分离: * 按时间分 :一个月一个目录,一个星期一个目录,一天一个目录 * 按数量分 :一个目录下存5000个文件,创建一个新的目录,再去存放. * 按用户分 :为每个用户创建一个单独目录 存放文件. * 按目录分离算法分 : * 使用唯一文件名.hashCode(); -- 得到一个代表当前这个文件的int类型值. * int类型占4个字节32位.可以让hashCode值&0xf; 得到一个int值,用这个int值作为一级目录. * 让hashCode右移4位 &0xf ;得到一个int值,用这个int值作为二级目录.依次类推. 1.1.4.3 Servlet3.0异步请求:[AppleScript] 纯文本查看 复制代码 /**
* 异步请求的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();
}
}
}
} 传智播客·黑马程序员郑州校区地址 河南省郑州市 高新区长椿路11号大学科技园(西区)东门8号楼三层 联系电话 0371-56061160/61/62 来校路线 地铁一号线梧桐街站A口出 |