我们需要先准备好2个apache的类:
上一个博客文章只讲了最简单的入门,现在来开始慢慢加深。
先过渡一下:只上传一个file项
index.jsp:
<h2>用apache的工具处理文件上传</h2> <!-- 先过渡一下:只上传一个file项 --> <form action="<%= request.getContextPath() %>/upload" method="post" enctype="multipart/form-data"> 文件:<input type="file" name="file"/><br/> <input type="submit" value="提交"/> </form>
web.xml:
<servlet> <servlet-name>UploadServlet</servlet-name> <servlet-class>cn.hncu.servlets.upload.UploadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>UploadServlet</servlet-name> <url-pattern>/upload</url-pattern> </servlet-mapping>
UploadServlet.java:
package cn.hncu.servlets.upload; import java.io.File; import java.io.IOException; import java.io.PrintWriter; 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.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FileUtils; public class UploadServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //下面这句解决上传文件名的中文乱码 //注意。下面这句设置中文,如果是“multipart/form-data”表单,可以设置其中file组件的文件名,但对其中的普通表单组件无效 //如果是"application/x-www-form-urlencoded"表单,可以设置其中的普通表单组件 request.setCharacterEncoding("utf-8"); //先获取所接收文件要保存的路径 String path = getServletContext().getRealPath("/imgs"); //文件上传需要临时目录(如果不指定,那么该目录就是tomcat/temp) File tempDiv = new File("E:/a"); if(!tempDiv.exists()){ tempDiv.mkdir(); } DiskFileItemFactory fileFactory = new DiskFileItemFactory(1024*8, tempDiv); //创建用于解析文件的工厂类,同时设置缓存区的大小和位置 //####思路的入口: ServletFileUpload upload = new ServletFileUpload(fileFactory); upload.setFileSizeMax(1024*1024*5);//设置单个文件上传最大为5M upload.setSizeMax(1024*1024*8);//所有上传文件大小之和的最大值,此处设最多能上传8M //setSizeMax方法用于设置请求消息实体内容的最大允许大小,以防止客户端故意通过上传特大的文件来塞满服务器端的存储空间,单位为字节。 //以下开始解析: //parseRequest是从查询字符串和请求体中获取参数赋值到paramMap,然后格式化uri,填充Request对象实例 try { List<FileItem> list = upload.parseRequest(request); for(FileItem fi:list){ // isFormField()。isFormField方法用来判断FileItem对象里面封装的数据是一个普通文本表单字段,还是一个文件表单字段。 //如果是普通文本表单字段,返回一个true否则返回一个false。 //因此可以用该方法判断是否是普通表单域还是文件上传表单域。 if(fi.isFormField()){ //普通表单组件,如:<input type="text" name="name"/> String str = fi.getString("utf-8");//以指定编码的方式获取,来解决普通表单组件的中文乱码问题 //将FileItem对象中保存的数据流内容以一个字符串返回。 System.out.println("普通表单组件:"+str); }else{//文件组件 String fileName = fi.getName();//获得上传文件的文件名 System.out.println("fileName:"+fileName); //由于上传的文件“名字”可能会有中文,而服务器目录当中的资源名称不能够用中文(带中文的文件在浏览器中无法访问的),因此要把它转换成非中文的文件名(要考虑文件名不能重复) //于是,我们用java自带的UUID类,自动生成 String uuid = UUID.randomUUID().toString().replace("-", "");//去掉uuid中的'-' String ext = fileName.substring(fileName.lastIndexOf("."));//截取文件的扩展名: .* //System.out.println("ext:"+ext); String newFileName = uuid+ext;//本地服务器存储的文件名 //System.out.println("newFileName:"+newFileName); //真正的文件内容在fi.getInputStream() 当中 FileUtils.copyInputStreamToFile(fi.getInputStream(), new File(path+"/"+newFileName));//拷贝的字节从InputStream源文件到目的地(file)。 } } } catch (FileUploadException e) { throw new RuntimeException(e); } } }
演示结果:
在这个上传中,我们并没有把uuid和文件名联系起来,这样是不好的,必须用数据库把uuid和其对应的文件名存起来。以后下载的时候还给客户端一样的名字,而不是给他uuid的名字。