这节课我们就来学怎么真正的上传文件
要想上传文件,我们需要引入新的第三方Jar包,两个:
- commons-fileupload
- commons-io
commons-fileupload依赖于commons-io
jar包一如既往的给大家准备好了,直接复制粘贴到/WEB-INF/lib下即可
OK,关键问题来了,怎么用。百度,准确的说是看官方文档,这节课就来教大家怎么去搜和看官方文档。
http://commons.apache.org/proper/commons-fileupload/
这个就是commons-fileupload的官网,可以看到也是属于Apache的,Apache我们不陌生了,我们用的Tomcat就是它家的
OK,继续看官网
全英文,头疼。但是,我们的谷歌浏览器不是吃素的。
OK,变成中文了,当然,翻译的质量肯定很差,很多时候需要切回英文去看,再点一下就切回英文了。
OK,我们看什么呢?显然是用户指南。
最简单的使用情况,显然可以直接复制粘贴,OK,我们开始写代码
// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();
// Configure a repository (to ensure a secure temp location is used)
ServletContext servletContext = this.getServletConfig().getServletContext();
File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Parse the request
List<FileItem> items = upload.parseRequest(request);
package com.servlet; 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 javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.util.Iterator; import java.util.List; import java.util.UUID; //负责文件上传的Servlet public class FileUploadServlet extends HttpServlet { //文件上传一定是POST方式,所以我们用doPost @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { //创建一个FileItemFactory,也就是FIleItem工厂 DiskFileItemFactory factory = new DiskFileItemFactory(); //设置临时存储区 ServletContext servletContext = this.getServletConfig().getServletContext(); File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir"); factory.setRepository(repository); //new一个ServletFileUpload对象 ServletFileUpload upload = new ServletFileUpload(factory); //解析request对象,获取FileItem集合 List<FileItem> items = upload.parseRequest(req); //处理上传的项目 //文档里代码的括号是中文的,真是讨厌 //替换一下,解决 Iterator<FileItem> iter = items.iterator(); while(iter.hasNext()){ FileItem item = iter.next(); if(item.isFormField()){ processFormField(item); } else { processUploadedFile(item); } } //OK,文件成功上传,下面开始解释 /** * 先来解释ServletContext.getRealPath()方法 * 这个方法就是根据相对路径获取真实路径,相对于谁的路径呢?相对于F:\code\java\JavaWebTeach01\out\artifacts\JavaWebTeach01_war_exploded的路径 * 当然,如果有ContextPath的话,那就是F:\code\java\JavaWebTeach01\out\artifacts\JavaWebTeach01_war_exploded\${ContextPath} * * 然后,为什么会是这个路径呢? * 这个是在ProjectStructure里设置的,Eclipse又不一样,它会编译到Tomcat的/webapps里,也就是下面这条路径 * F:\tomcat8.5\apache-tomcat-8.5.35\webapps * * idea的就直接在项目下的out/artifacts/项目名_war_exploded下 * * web下的东西会全部编译到out/artifacts/项目名_war_exploded下 * src里的源代码会被编译成.class文件存放在/WEB-INF/classes下 * * 刚刚我新建了一个upload文件夹,然后放了个1.txt,注意,在idea里,web目录下的空文件夹不会被编译到out下,因此必须放个文件 * 还有,我的文件上传是上传到了out下的upload,web下的upload里只会有一个1.txt * 这就是全部的文件上传 */ } catch (FileUploadException e) { e.printStackTrace(); } } //处理上传文件,这里的item保存着文件流 private void processUploadedFile(FileItem item) throws IOException { //处理文件上传 if(!item.isFormField()){ //获取文件对应的属性名,就是input标签里的name属性值 String fieldName = item.getFieldName(); //获取文件名 String fileName = item.getName(); //获取文件类型 String contentType = item.getContentType(); //判断是否在内存中 boolean isInMemory = item.isInMemory(); //获取文件大小 long sizeInBytes = item.getSize(); //OK,之后自己写 //接下来我们就是读文件内容,然后保存到自己设置的文件夹里 InputStream inputStream = item.getInputStream(); byte[] bytes = new byte[(int)sizeInBytes]; inputStream.read(bytes); //这样要上传的文件的数据就都在bytes里了,接下来我们写到指定文件夹里就可以了 //别忘了close掉inoutStream inputStream.close(); //获取文件后缀名 String fileSuffixName = fileName.substring(fileName.lastIndexOf(".")); //然后设置我们想要的文件名即可 //但有一点,文件名不可以重复,因此我们还需要一个随机文件名生成器 //java自带这玩意,类名叫UUID String newFileName = UUID.randomUUID().toString() + fileSuffixName; System.out.println("新文件名: " + newFileName); String path = this.getServletContext().getRealPath("/upload"); //File.separator就是文件分隔符,可以根据不同平台显示不同分隔符,windows就是\,Linux就是/ newFileName = path + File.separator + newFileName; System.out.println("新文件的完整路径: \n" + newFileName); File file = new File(newFileName); if (!file.exists()) { file.createNewFile(); OutputStream outputStream = new FileOutputStream(file); outputStream.write(bytes); //别忘了close掉OutputStream outputStream.close(); } } } //处理form表单数据,这类数据是字符串 private void processFormField(FileItem item) { //处理常规表单字段 if(item.isFormField()){ String name = item.getFieldName(); String value = item.getString(); System.out.println("name: " + name); System.out.println("value: " + value); } } }