文件上传
1.普通表单提交默认enctype="application/x-www-form-urlencoded";但是当表单中存在文件类型时,需要设置enctype="multipart/form-data",它不对字符进行编码,用于发送二进制的文件(即所有文件类型,如视频、图片、音乐、文档都可以用此类型entype);还有一种enctype="text/plain"用于发送纯文本内容。
2.表单请求方式必须为post。
3.接收时不能再用request.getParameter(),而是request.getInputStream()解析二进制流,得到ServletInputStream对象。
当我们使用request.getInput直接获取到的字节流,后续进行打印数据的时候。会自动加上许多表单,文件的属性和属性值,还有分隔符。上传的是纯文本文件时,打印出来还能看到清除文件内容。但当上传的是非文本文件的时候,自动加上的属性和属性值,会导致文件不能正常显示。这时候我们就需要解析request.getInpustream()。
FileUpload文件上传
FileUpload是apache的commons组件提供的上传组件,它最主要的工作就是帮我们解析request.getInpustream()。可以参考在线API文档:http://tool.oschina.net/apidocs/apidoc?api=commons-fileupload
使用fileUpload组件首先需要引入两个jar包
- commons-fileUpload.jar
-
commons-io.jar
image
fileUpload的核心类有DiskFileItemFactory、ServletFileUpload、FileItem。
使用fileUpload固定步骤:
- 创建工厂类:DiskFileItemFactory factory=new DiskFileItemFactory();
- 创建解析器:ServletFileUpload upload=new ServletFileUpload(factory);
- 使用解析器解析request对象:List<FileItem> list=upload.parseRequest(request);
使用的基本思想:
- commons-fileupload 可以解析请求, 得到一个 FileItem 对象组成的 List
- commons-fileupload 把所有的请求信息都解析为 FileItem 对象, 无论是一个一般的文本域还是一个文件域.
- 可以调用 FileItem 的 isFormField() 方法来判断是一个 表单域 或不是表单域(则是一个文件域)
- 再来进一步获取信息
一个FileItem对象对应一个表单项。FileItem类有如下方法:
- String getFieldName():获取表单项的name的属性值。
- String getName():获取文件字段的文件名。如果是普通字段,则返回null
- String getString():获取字段的内容。如果是普通字段,则是它的value值;如果是文件字段,则是文件内容。
- String getContentType():获取上传的文件类型,例如text/plain、image。如果是普通字段,则返回null。
- long getSize():获取字段内容的大小,单位是字节。
- boolean isFormField():判断是否是普通表单字段,若是,返回true,否则返回false。
- InputStream getInputStream():获得文件内容的输入流。如果是普通字段,则返回value值的输入流。
文件名中文乱码处理:
- servletFileUpload.setHeaderEncoding("utf-8") 或 request.setCharacterEncoding("utf-8");
表单普通字段中文乱码处理:
- new String(str.getBytes("iso-8859-1","utf-8"));
设置内存缓冲区的大小,默认为10KB:
- diskFileItemFactory.setSizeThreshold(10241024);*
指定临时文件目录,如果单个文件的大小超过内存缓冲区,该文件将会临时缓存在此目录下:
- diskFileItemFactory.setRepository(file);
设置单个文件大小限制,如果有某个文件超过此大小,将抛出FileUploadBase.FileSizeLimitExceededException
- servletFileUpload.setFileSizeMax(1024102410);**
设置所有文件,也就是请求大小限制,如果文件总和超过此大小,将抛出FileUploadBase.SizeLimitExceededException
- servletFileUpload.setSizeMax(1024102420);**
利用UUID生成伪随机字符串作为文件名避免重复:UUID.randomUUID().toString();
将文件写到硬盘上。写完之后,系统会自动将放在临时文件目录的该文件删除:
- fileItem.write(new File(path,fileName));
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="upd" method="post" enctype="multipart/form-data">
文件名<input type="text" name="filename">
文件: <input type="file" name="file"><br>
<input type="submit">
</form>
<form action="uploadServlet" method="post" enctype="multipart/form-data">
File: <input type="file" name="file"><br>
文本域: <input type="text" name="text"><br>
<input type="submit">
</form>
<form action="uploadServlet" method="post" enctype="multipart/form-data">
文本域: <input type="text" name="text"><br>
<input type="submit">
</form>
</body>
</html>
package com.kylin.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 org.apache.commons.io.FileUtils;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
@WebServlet("/uploadServlet")
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置当超过文件的大小,就将文件写入到一个临时文件中
factory.setSizeThreshold(1024 * 500);
File tempDirectory = new File("C:\\Data\\Log");
factory.setRepository(tempDirectory);
ServletFileUpload upload = new ServletFileUpload(factory);
// //设置单个文件大小限制
// upload.setFileSizeMax(1024*1024*10);
// //设置所有文件总和大小限制
// upload.setSizeMax(1024*1024*30);
//解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
try {
//1.得到FileItem的集合items
List<FileItem> items = upload.parseRequest(req);
//2.遍历items 若是一个一般的表单域,打印信息
for (FileItem item : items) {
if (item.isFormField()) {
String name = item.getFieldName();
String value = item.getString("utf-8");//解决一般表单域的乱码问题
System.out.println(name + ": " + value);
} else {
//若是文件域则把文件保存到指定的目录下,
String fieldName = item.getFieldName();
String fileName = item.getName();
String contentype = item.getContentType();
long sizeInBytes = item.getSize();
System.out.println(fieldName);
System.out.println(fileName);
System.out.println(contentype);
System.out.println(sizeInBytes);
/* InputStream in = item.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
fileName = "C:\\Data\\Log\\" + fileName;
System.out.println(fileName);
OutputStream out = new FileOutputStream(fileName);
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.close();
in.close();*/
String suffix = fileName.substring(fileName.lastIndexOf("."));//截取文件后缀名
String uuid = UUID.randomUUID().toString();//制造唯一文件名
FileUtils.copyInputStreamToFile(item.getInputStream(), new File("C:\\Data\\IDM\\Java学习\\" + uuid + suffix));
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
}