【Java EE 学习 22 上】【文件上传】【目录打散】【文件重命名】
1.文件上传概述
(1)使用<input type="file">的方式来声明一个文件域。
(2)表单提交方式一定要是post方式才行
(3)表单属性enctype
默认提交属性:application/x-www-form-urlencoded 这个类型表示传递的是键值对类型
需要改成:multipart/form-data 这个类型表示将要传递的是字节码类型
(4)使用httpWatch查看http协议的请求部分,可以发现
在Content-type后面的boundary是分界符,用以分割头部信息和正文部分,正文部分是以开始的部分,结束部分则以
来标识,可以看出结束的标识比开始的标志多了两个--。
2.文件上传准备
(1)需要的两个jar包:
commons-fileupload.jar :文件上传的核心包
commons-io.jar :文件上传可能会使用的工具包,该工具包中提供了一个从流中将数据写到文件的简便方法。
(2)几个核心类
DiskFileItemFactory类
|-方法setSizeThreshold :设置一个临界值,如果上传的单个文件小于该值,将不会借助临时临时文件存储上传的文件;反之,如果大于该值则服务器将会借助临时文件暂存上传的文件,默认值是10KB。
|-方法setRepository :设置一个临时目录用于暂存上传的数据。
ServletFileUpload类
|-该类接收DiskFileItemFactory类的实例
|-setSizeMax方法 :设置可接受的上传的所有文件的大小之和
|-setFileSizeMax方法 :设置可以上传的单个文件的大小
|-parseRequest方法 :解析HttpServletRequest对象,从中拿到所有上传文件的信息,返回List结果集
FileItem类
|-该类是ServletFileUpload类的方法parseRequest的返回值List的元素类型即List<FileItem>
|-getName方法 :获取上传文件的文件名,带有全路径
|-getContentType :得到文件类型,该类型并不是判断后缀名得到的,也就是说即使更改文本文件的扩展名为.jpg,文件类型也不会是图片,仍然是文本类型
|-getInputStream :该方法返回一个输入字节流,通过读取该字节流就可以获得该文件并保存到服务器。
|-delete方法 :该方法的作用是销毁FileItem对象,在销毁该对象的同时也会在服务器上将对应的临时文件删除,虽然理论上就算不调用该方法,临时文件也会最终被删除,但是强烈推荐手动调用该方法,这样可以尽快删除临时文件,节省存储空间,但是应当重点强调的是,调用该方法的时候必须将输入流和输出流统统close掉,否则可能会由于文件占用而导致临时文件删除不掉。
3.上传单个文件
(1)JSP文件
<%@ page language="java" import="java.util.*" pageEncoding="utf-8" contentType="text/html; charset=utf-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!-- 简单的文件上传示例 --> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <title>Insert title here!</title> <style type="text/css"> table{ border: 1px solid black; border-collapse: collapse; margin: 0 auto; margin-top: 100px; } td { border: 1px solid black; text-align: center; padding: 3px; } </style> </head> <body> <form action="<c:url value='/uploadSingleFileServlet1'/>" method="post" enctype="multipart/form-data"> <table> <tr> <td>文件</td> <td><input type="file" name="file"></td> </tr> <tr> <td colspan="2"><input type="submit" value="上传"></td> </tr> </table> </form> </body> </html>
(2)Servlet文件
package com.kdyzm.servlet; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.List; 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; public class UploadSingleFileServlet1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); //接收上传的请求,读取上传的文件 //获取存放上传文件的上传文件夹 String path=this.getServletContext().getRealPath("/upload"); //第一步:声明一个磁盘文件项目工厂类,用于指定一个磁盘空间存放上传文件 DiskFileItemFactory dfif=new DiskFileItemFactory(); dfif.setRepository(new File(this.getServletContext().getRealPath("/temp")));//声明缓存目录 dfif.setSizeThreshold(1024*10);//小于10KB留在内存,大于10KB保存到文件 //第二步:声明ServletFileUpload接收上面的目录 ServletFileUpload sfu=new ServletFileUpload(dfif); //第三步:解析Request try { List<FileItem>list=sfu.parseRequest(request);//解析请求HttpServletRequest //假设只有一个文件 FileItem file=list.get(0); //获取文件名,改文件名带有路径 String fileName=file.getName(); fileName=fileName.substring(fileName.lastIndexOf("\")+1); //获取文件类型 String fileType=file.getContentType(); //获取输入字节流 InputStream is=file.getInputStream(); long fileSize=is.available(); FileOutputStream fos =new FileOutputStream(new File(path+"/"+fileName)); int length=-1; byte []buff=new byte[1024*1024]; while((length=is.read(buff))!=-1) { fos.write(buff, 0, length); } fos.close(); is.close();//这个流必须关闭,否则不能删除临时文件 //删除临时文件的动作必须在流关闭之后。应当是文件占用的问题造成的失败。 file.delete(); PrintWriter pw=response.getWriter(); pw.println("上传成功!<br/>文件名为:"+fileName); pw.println("<br/>文件大小为:"+fileSize+"Byte"); pw.println("<br/>文件类型为:"+fileType); //删除临时文件,伴随着FileItem对象的删除,实际存储在磁盘上的文件也被删除 } catch (FileUploadException e) { e.printStackTrace(); } } }