在Servlet3.0之前,form表单的文件上传需要接触common-fileupload等工具。
在Servlet3.0中,HttpServletRequest增加了对文件上传到的支持。
Http Servlet Request提供了如下两个方法来处理文件的上传:
Part getPart(String name):根据名称来获取文件上传域
Collection<Part> getParts():获取所有的文件上传域
Part对象位于javax.servlet.http.Part。该对象提供了访问文件类型、大小、输入流等方法,还提供了一个write(String file)方法将文件上传到服务器的制定文件夹中。
表单中的<input type="file">为文件域,需要指定其enctype属性。
enctype属性有三个值:
application/x-www-form-urlencode
multipart/form-data
text/plain
第一种,也是默认的enctype属性值。提交表单时只会发送文件域中的文本框里字符串。即所选文件的绝对路径。(貌似没什么卵用)
第二种,就是应该设置的值。这种编码方式会以二进制流的方式来处理表单数据,会把指定的文件内容封装进请求参数中。
第三种,适用于表单的action属性为mailto:URL时,即通过表单直接发送邮件的方式。
下面看示例:
servlet3\upload.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<!DOCTYPE html>
<html>
<head>
<title>文件上传</title>
</head>
<body>
<form method="post" action="upload" enctype="multipart/form-data"> //这里要说一下action。此处不加"/",表示相对路径。
文件名:<input type="text" id="name" name="name" /><br/> //因为Servlet设置的url就是"/upload",也就意味着Servlet和此jsp都位于项目
选择文件:<input type="file" id="file" name="file" /><br/> //根目录下(即http://loacalhost:8888/servlet3目录).
<input type="submit" value="上传" /><br/> //如果加上"/",路径表示的是服务器路径下。就找不到Servlet了。
</form>
</body>
</html>
下面是:servlet3\WEB-INF\src\lee\UploadServlet.java
package lee;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.annotation.*;
import java.io.PrintWriter;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Part;
import java.util.Collection;
@WebServlet(name="upload",urlPatterns={"/upload"})
//处理文件上传的Servlet需要使用@MultipartConfig注解来修饰
@MultipartConfig
public class UploadServlet extends HttpServlet{
public void service (HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
//response.setContentType()用来设置响应的报头信息。
response.setContentType("text/html; charset=GBK");
//response.getWriter()获取响应的对象输出流
PrintWriter out = response.getWriter();
//request.setCharacterEncoding()对客户端请求进行重新编码
request.setCharacterEncoding("GBK");
//request.getParameter()获取指定的请求参数值
String name = request.getParameter("name");
//输出参数值
out.println("普通的name参数为:"+name+"<br/>");
//request.getPart()获取指定的文件上传域。还有getParts()来获取所有的文件上传域
Part part = request.getPart("file");
//part.getContentType()获取part上传文件的文件类型
out.println("上传文件的类型为:"+part.getContentType()+"<br/>");
//part.getHeaderNames()获取文件上传域的Header Name
Collection<String> headerNames = part.getHeaderNames();
for(String headerName : headerNames){
out.println(headerName+"--->"+part.getHeader(headerName)+"<br/>");
}
String fileNameInfo = part.getHeader("content-disposition");
String fileName=fileNameInfo.substring(fileNameInfo.indexOf("filename=\"")+10,fileNameInfo.length() - 1);
part.write(getServletContext().getRealPath("/uploadFiles")+"/"+fileName); //要提前在项目目录下建一个文件夹。
}
}
public void service (HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{
//response.setContentType()用来设置响应的报头信息。
response.setContentType("text/html; charset=GBK");
//response.getWriter()获取响应的对象输出流
PrintWriter out = response.getWriter();
//request.setCharacterEncoding()对客户端请求进行重新编码
request.setCharacterEncoding("GBK");
//request.getParameter()获取指定的请求参数值
String name = request.getParameter("name");
//输出参数值
out.println("普通的name参数为:"+name+"<br/>");
//request.getPart()获取指定的文件上传域。还有getParts()来获取所有的文件上传域
Part part = request.getPart("file");
//part.getContentType()获取part上传文件的文件类型
out.println("上传文件的类型为:"+part.getContentType()+"<br/>");
//part.getHeaderNames()获取文件上传域的Header Name
Collection<String> headerNames = part.getHeaderNames();
for(String headerName : headerNames){
out.println(headerName+"--->"+part.getHeader(headerName)+"<br/>");
}
String fileNameInfo = part.getHeader("content-disposition");
String fileName=fileNameInfo.substring(fileNameInfo.indexOf("filename=\"")+10,fileNameInfo.length() - 1);
part.write(getServletContext().getRealPath("/uploadFiles")+"/"+fileName); //要提前在项目目录下建一个文件夹。
}
}
此Servlet使用了注解类进行Servlet配置。
当然也可以在web.xml中配置:如下web.xml
<?xml version="1.0" encoding="GBK"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1" metadata-complete="false"> //此处metadata-complete="false"表示可以使用注解。为true时,Servlet中的注解就没用了。
<!--配置Web应用的首页列表-->
<welcome-file-list>
</welcome-file-list>
<servlet>
<servlet-name>upload</servlet-name>
<servlet-class>lee.UploadServlet</servlet-class> //servlet-class为自动找位于classes文件夹中的类。写法为: 包名.类名。不需要指定classes
</servlet>
<servlet-mapping>
<servlet-name>upload</servlet-name>
<url-pattern>/upload</url-pattern>
</servlet-mapping>
</web-app>
如此几步,就可以完成文件的上传。
下面使用commons-fileupload来处理文件上传。
1:导入必要的commoms-fileupload、commons-io两个jar包。
2:form设置enctype="multipart/form-data"。
3:Servlet中创建DiskFileItemFactory对象。
4:使用DiskFileItemFactory对象作为参数创建ServletFileUpload对象。如:upload
5:使用upload.setHeaderEncoding("xxx")来设置文件编码
6:使用upload.parseRequest(HttpServletRequest request)方法来解析出所有表单域:List<FileItem> fileItemList。
7:用FileItem的实例方法:isFormField()来判断是否为普通表单域。
8:对普通的表单域进行普通的操作,其中,可以使用FileItem的实例方法:getFieldName()、getString()来分别获取表单控件的name以及value。
9:对文件上传域,使用FileItem的实例方法:write(File file)来将文件写到指定位置。可以使用FileItem 的实例方法:getFileName()来获取文件上传控件的name值,getName()来获取文件名。