共计 4119 个字符,预计需要花费 11 分钟才能阅读完成。
1、文件上传的作用
例如网络硬盘!就是用来上传下载文件的。
往百度网盘上传一个文件就是文件上传。
2、文件上传对页面的要求
上传文件的要求比较多,需要记一下:
- 必须使用表单,而不能是超链接;
- 表单的 method 必须是 POST,而不能是 GET;
- 表单的 enctype 必须是 multipart/form-data;
- 在表单中添加 file 表单字段,即 <input type=”file”…/>
例如:
<form action="${pageContext.request.contextPath}/FileUploadServlet" method="post" enctype="multipart/form-data"> | |
用户名:<input type="text" name="username"/><br/> | |
文件 1:<input type="file" name="file1"/><br/> | |
文件 2:<input type="file" name="file2"/><br/> | |
<input type="submit" value="提交"/> | |
</form> | |
3、文件上传对 Servlet 的要求
当提交的表单是文件上传表单时,那么对 Servlet 也是有要求的。
首先我们要肯定一点,文件上传表单的数据也是被封装到 request 对象中的。
**request.getParameter(String)** 方法获取指定的表单字段字符内容,但文件上传表单已经不在是字符内容,而是字节内容,所以失效。
这时可以使用 request 的 getInputStream() 方法获取 ServletInputStream 对象,它是 InputStream 的子类,这个 ServletInputStream 对象对应整个表单的正文部分(从第一个分隔线开始,到最后),这说明我们需要的解析流中的数据。当然解析它是很麻烦的一件事情,而 Apache 已经帮我们提供了解析它的工具:commons-fileupload。
可以尝试把 request.getInputStream() 这个流中的内容打印出来看看
public void doPost(HttpServletRequest request, HttpServletResponse response) | |
throws ServletException, IOException {InputStream in = request.getInputStream(); | |
String s = IOUtils.toString(in); // 使用 apache 的 commons 的 io 组件,把流中的数据读取出来转换成字符串 | |
System.out.println(s); | |
} |
-----------------------------7ddd3370ab2 | |
Content-Disposition: form-data; name="username" | |
hello | |
-----------------------------7ddd3370ab2 | |
Content-Disposition: form-data; name="file1"; filename="a.txt" | |
Content-Type: text/plain | |
aaa | |
-----------------------------7ddd3370ab2 | |
Content-Disposition: form-data; name="file2"; filename="b.txt" | |
Content-Type: text/plain | |
bbb | |
-----------------------------7ddd3370ab2-- |
4、commons-fileupload 工具介绍
4.1、fileupload 概述
fileupload 是由 apache 的 commons 组件提供的上传组件。它最主要的工作就是帮我们解析 request.getInputStream()。
fileupload 组件需要的 JAR 包有:
-
commons-fileupload.jar,核心包;
-
commons-io.jar,依赖包。
4.2、fileupload 简单应用
fileupload 的核心类有:DiskFileItemFactory、ServletFileUpload、FileItem。
使用 fileupload 组件的步骤如下:
-
创建工厂类 DiskFileItemFactory 对象:DiskFileItemFactory factory = new DiskFileItemFactory()
-
使用工厂创建解析器对象:ServletFileUpload fileUpload = new ServletFileUpload(factory)
-
使用解析器来解析 request 对象:List
list = fileUpload.parseRequest(request)
隆重介绍 FileItem 类,它才是我们最终要的结果。一个 FileItem 对象对应一个表单项(表单字段)。一个表单中存在文件字段和普通字段,可以使用 FileItem 类的 isFormField() 方法来判断表单字段是否为普通字段,如果不是普通字段,那么就是文件字段了。
-
String getName():获取文件字段的文件名称;
-
String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件;
-
String getFieldName():获取字段名称,例如:,返回的是 username;
-
String getContentType():获取上传的文件的类型,例如:text/plain。
-
int getSize():获取上传文件的大小;
-
boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回 false,说明是文件字段;
-
InputStream getInputStream():获取上传文件对应的输入流;
-
void write(File):把上传的文件保存到指定文件中。
4.3、简单上传示例
写一个简单的上传示例:
-
表单包含一个用户名字段,以及一个文件字段;
-
Servlet 保存上传的文件到 uploads 目录,显示用户名,文件名,文件大小,文件类型。
第一步:
完成 index.jsp,只需要一个表单。注意表单必须是 post 的,而且 enctype 必须是 mulitpart/form-data 的。
<form action="${pageContext.request.contextPath}/FileUploadServlet" method="post" enctype="multipart/form-data"> | |
用户名:<input type="text" name="username"/><br/> | |
文件 1:<input type="file" name="file1"/><br/> | |
<input type="submit" value="提交"/> | |
</form> |
第二步:
完成 FileUploadServlet
public void doPost(HttpServletRequest request, HttpServletResponse response) | |
throws ServletException, IOException {// 因为要使用 response 打印,所以设置其编码 | |
response.setContentType("text/html;charset=utf-8"); | |
// 创建工厂 | |
DiskFileItemFactory dfif = new DiskFileItemFactory(); | |
// 使用工厂创建解析器对象 | |
ServletFileUpload fileUpload = new ServletFileUpload(dfif); | |
try {// 使用解析器对象解析 request,得到 FileItem 列表 | |
List<FileItem> list = fileUpload.parseRequest(request); | |
// 遍历所有表单项 | |
for(FileItem fileItem : list) {// 如果当前表单项为普通表单项 | |
if(fileItem.isFormField()) {// 获取当前表单项的字段名称 | |
String fieldName = fileItem.getFieldName(); | |
// 如果当前表单项的字段名为 username | |
if(fieldName.equals("username")) {// 打印当前表单项的内容,即用户在 username 表单项中输入的内容 | |
response.getWriter().print("用户名:" + fileItem.getString() + "<br/>"); | |
} | |
} else {// 如果当前表单项不是普通表单项,说明就是文件字段 | |
String name = fileItem.getName();// 获取上传文件的名称 | |
// 如果上传的文件名称为空,即没有指定上传文件 | |
if(name == null || name.isEmpty()) {continue; | |
} | |
// 获取真实路径,对应 ${项目目录}/uploads,当然,这个目录必须存在 | |
String savepath = this.getServletContext().getRealPath("/uploads"); | |
// 通过 uploads 目录和文件名称来创建 File 对象 | |
File file = new File(savepath, name); | |
// 把上传文件保存到指定位置 | |
fileItem.write(file); | |
// 打印上传文件的名称 | |
response.getWriter().print("上传文件名:" + name + "<br/>"); | |
// 打印上传文件的大小 | |
response.getWriter().print("上传文件大小:" + fileItem.getSize() + "<br/>"); | |
// 打印上传文件的类型 | |
response.getWriter().print("上传文件类型:" + fileItem.getContentType() + "<br/>"); | |
} | |
} | |
} catch (Exception e) {throw new ServletException(e); | |
} | |
} |
