javaweb|文件上传
第 11 章 文件上传
注意
http协议允许用户以请求形式将本地文档上传到服务器,这部分将涉及到二进制数据的处理,java开源社区提供了许多处理文件上传的工具包,所以我们仅仅介绍上传的原理流程和工具配置,不会重新制造轮子。
如果你不满足以下任一条件,请继续阅读,否则请跳过此后的部分,进入下一章:第 12 章 导出文件。
-
了解http使用POST和GET发送请求的区别。
-
了解如何使用html表单上传文件。
-
了解使用commons-fileupload处理用户上传的文件。
用户点击浏览选择需要上传的本地文件,然后点击提交上传到服务器。
文件列表中显示已上传文件的名称,大小和上传时间,可以点击文件名浏览或下载文件,也可以点击删除删除文件。
请看一下这里的temp和upload目录,commons-fileupload会把从请求中接收到的文件临时保存在temp目录下等待处理,我们可以使用write()方法将临时文件移动到我们指定的目录,也可以直接用delete()方法删除。
upload目录是上传文件的存放目录,上传成功的文件最后都会保存到这个目录下。
为了使用commons-fileupload处理上传文件,需要把两个依赖包放到WEB-INF/lib目录下。
这样就能在UploadServlet.java中使用commons-fileupload了,处理上传的save()方法如下:
public void save(HttpServletRequest request,HttpServletResponse response) throws Exception { String temp = getServletContext().getRealPath("/temp"); // 上传时存放临时文件的目录 String uploadDir = getServletContext().getRealPath("/upload"); // 上传文件存放的目录 DiskFileUpload diskFileUpload = new DiskFileUpload(); diskFileUpload.setSizeMax(1*1024*1024); // 设置允许用户上传文件大小,单位:字节 diskFileUpload.setSizeThreshold(4096); // 设置最多只允许在内存中存储的数据,单位:字节 diskFileUpload.setRepositoryPath(temp); // 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录 //开始读取上传信息 List fileItems = diskFileUpload.parseRequest(request); Iterator iter = fileItems.iterator(); // 依次处理每个上传的文件 while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); // 忽略其他不是文件域的所有表单信息 if (!item.isFormField()) { String name = item.getName(); // 获取上传文件名,包括路径 name = name.substring(name.lastIndexOf("\\") + 1); // 从全路径中提取文件名 long size = item.getSize(); if (name != null && !name.equals("") && size != 0) { String filePath = System.currentTimeMillis() + "_" + name; item.write(new File(uploadDir, filePath)); Upload upload = new Upload(); upload.setFileName(name); upload.setFilePath("upload/" + filePath); upload.setFileSize(size); upload.setAddDate(new Date()); list.add(upload); } } } response.sendRedirect("index.jsp"); }
getServletPath().getRealPath("/temp")将得到“tomcat安装目录 + /webapps + /temp”,这是我们获得服务器下目录下唯一方法,得到了这个完整路径后才可以决定将文件保存到什么地方。
处理文件上传的第一步是创建一个DiskFileUpload,为它设置临时目录,文件大小限制,内存缓存的大小。
得到DiskFileUpload实例后,调用parseRequest(request)解析请求,解析的结果是一个列表,因为我们可能上传多个问题见。
现在可以循环得到的列表处理每一个FileItem,如果isFormField()返回false,表示当前FileItem对应一个上传的文件,下面就能从FileItem中获得文件名和文件大小,最后调用write()方法写入upload目录下。
调用write()之后,temp目录下对应的临时文件自动会被删除,如果想保存文件的具体信息,还需要进行另外的处理,这里我们使用的是一个自定义javabean,每次上传成功后会创建一个Upload,将文件名,文件保存的路径,文件大小,上传时间加入UploadServlet中定义的list变量中,下次执行upload.do?method=list请求的时候会将其中保存的数据显示到list.jsp中。当然如果服务器重启后内存中的数据就会丢失,实际开发时我们需要将上传信息保存到数据库中。
文件上传需要客户端与服务器端配合工作,客户端的浏览器必须将文件内容附加到http协议请求中,这样服务器才能处理。
浏览器端有几点需要注意的。
-
使用method="GET"。
表单默认使用method="GET"提交请求,GET方式的请求是没有请求体(body)的,所有参数都将附加到url后传递给服务器。
文件上传需要将二进制数据放到请求体(body)中,所以我们必须指定表单使用method="POST"。
-
为表单设置enctype="multipart/form-data"。
不设置enctype的情况表单只会把文件名传递到服务器,enctype的效果是把本地文件以二进制的形式附加到请求的body中,供服务器接收解析。
No comments:
Post a Comment