利用Servlet 3.0 的新特性可以轻松实现从客户端上传文件到服务器的功能。
原理:
首先介绍HttpServletRequest类中包含的涉及到文件上传的2个函数:
① Part getPart(String name):根据文件名来获取文件上传域。
② Collection<Part> getParts():获取所有文件的上传域。
上面两个方法的返回值都涉及到一个API:Part。每个Part对象对应于一个文件上传域,该对象提供了大量的方法来访问上传文件的文件类型、大小、输入流等,并提供了一个write(String file)方法将上传的文件写入服务器的本地磁盘。
为了向服务器上传文件,需要在表单里使用<input type="file".../>文件域,这个文件域会在HTML页面上产生一个单行文本框和一个“浏览”按钮,浏览者可通过该按钮选择需要上传的文件。
除此之外,上传文件一定要为表单域设置enctype属性。该属性指定的是表单数据的编码方式,有如下3个属性值:
① application/x-www-form-urlencoded:这是默认的编码方式,它只处理表单域里的value属性值,采用这种编码方式的表单会将表单域的值处理成URL的编码方式。② multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数里。③ text/plain:这种编码方式当表单的action属性为mailto:URL的形式时比较方便,这种方式主要适用于直接通过表单发送邮件。
如果不设置enctype属性或将其设置为application/x-www-form-urlencoded,提交表单时只会发送文件域中文本框内的字符串,也就是浏览者所选择文件的绝对路径,对服务器获取该文件没有任何作用,因为服务器不可能访问到客户机的文件系统。我们需要设置enctype="multipart/form-data"。
最后需要注意的是:处理上传文件功能的Servlet需要用@MultipartConfig来修饰。
示例:
下面给出一个简单的样例。
首先是前端页面的JSP文件,代码如下:
最后需要注意的是:处理上传文件功能的Servlet需要用@MultipartConfig来修饰。
示例:
下面给出一个简单的样例。
首先是前端页面的JSP文件,代码如下:
<%@ page language="java" contentType="text/html; charset=GBK"
pageEncoding="GBK"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK">
<title><s:text name="loginPage"/></title>
</head>
<body>
<form method="post" action="upload" enctype="multipart/form-data">
<input type="file" id="file" name="file" />
<input type="submit" value="upload" />
</form>
</body>
</html>
注意设定表单的enctype属性为multipart/form-data,另外请求方法必须是POST,笔者亲测发现,用GET会出异常。
接下来是Servlet类,代码如下:
package fileUploadDemo;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
/**
* A simple servlet class for file uploading.
* @author Octopusfly
* @version 2017-01-24.
*/
@MultipartConfig
public class FileUploadServlet
extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
public void service(
HttpServletRequest request,
HttpServletResponse response) {
try {
Part part = request.getPart("file");
part.write("E:\\received");
response.getWriter().println("<html>");
response.getWriter().println("<body>");
response.getWriter().println("File uploaded!");
response.getWriter().println("</body>");
response.getWriter().println("</html>");
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServletException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
服务端调用getPart方法,就可以得到上传文件的字节流,然后调用write方法,就可以将文件写入到本地,这里仅仅为了便于演示,笔者写入到E盘根目录,同时将文件名设定为received。
演示:
配置Servlet,启动Tomcat服务器后,访问index.jsp页面,可以看到下面的界面: