文件上传
-
什么是文件上传
将本地磁盘文件通过IO写入到服务器的过程
-
文件上传的技术
Servlet3.0
JSPSmartUpload
FileUpload
(这个是通用的技术,不像前面两个需要对应引擎的支持,依托于环境)- 框架(其实框架中的文件上传技术就是
FileUpload
技术的封装)
-
文件上传的三要素
-
表单的提交方式必须为
POST
-
表单中需要有文件上传表单项,必须有name属性
<input type="file" name="upload">
-
表单的
enctype
属性的值必须为multipart/form-data
- 如果没有设置
enctype
属性,那么在请求中对应的upload
只能获取到文件的名字
在请求头中(只有表单提交的请求中才有
content-Type
)
在请求体中
-
如果在form属性中设置了
enctype="multipart/form-data"
在请求头中
在请求体中(在火狐浏览器中才能看到)
- 如果没有设置
-
FileUpload
-
使用
fileUpload
组件首先需要引入两个jar包:commons-fileUpload.jar
commons-io.jar
-
编码问题
-
文件名乱码(防止文件路径中的中文乱码)
使用
servletFileUpload.setHeaderEncoding("UTF-8");
(通用方法,因为上传文件不一定是在servlet中)或者request.setCharacterEncoding("UTF-8")
都可以。(原理:虽然在表单页面是以utf-8
的编码提交的中文,但是在FileUpload
组件中默认是用ISO-8859-1
来解码,编码和解码的标准都不一样,自然会出现乱码) -
表单内容乱码
使用
getString("utf-8")
即可,也就是在获取内容时,就可以设置编码。
-
-
如果表单中设置了
enctype="multipart/form-data"
,那么将不能用request.getParameter()
来获得请求参数的值。必须先获得每个FileItem
部分,再通过它的方法来获取。
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1、创建磁盘文件项工厂类对象
// 不传入参数,使用默认的缓存区大小(10kb)和默认的临时文件存放的位置
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
// 2、创建核心解析类对象
ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory);
// 处理文件路径中(文件名)为中文出现乱码的情况
fileUpload.setHeaderEncoding("utf-8");
try {
// 3、解析请求对象,将请求分成几个部分(FileItem)
List<FileItem> list = fileUpload.parseRequest(request);
// 4、遍历集合获得每个部分的对象
for (FileItem fileItem : list) {
// 判断是否是普通表单项,是返回true,不是返回false
if (fileItem.isFormField()) {
// 获得普通项的参数名
String name = fileItem.getFieldName();
// 获得普通项的参数值,传入解码参数值的编码,不传默认是"ISO-8859-1"
String value = fileItem.getString("UTF-8");
} else {// 是文件上传项
// 获得文件上传项的参数名
String name = fileItem.getFieldName();
// 获得文件上传项的文件名
String fileName = fileItem.getName();
// 获得文件上传项的文件输入流
InputStream is = fileItem.getInputStream();
//生成唯一的文件名
String exName=fileName.substring(fileName.lastIndexOf("."));
String uuid=UUID.randomUUID().toString().replace("-","");
String uuidFileName=uuid+exName;
// 获得在服务器中保存这些上传文件的磁盘绝对路径(物理路径)
String path = this.getServletContext().getRealPath("/upload") + "\\" + uuidFileName;
OutputStream os = new FileOutputStream(new File(path));
int len = 0;
byte[] b = new byte[1024];
// 从文件的输入流中读取,再写到服务器中指定的文件里
while ((len = is.read(b)) != -1) {
os.write(b, 0, len);
}
os.close();
is.close();
}
}
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}