HttpServlet实现上传文件
当客户端向服务器上传文件时,客户端发送的Http请求正文采取"multipart/form-data"数据类型,它表示复杂的包括多个子部分的复合表单。
下面的upload.html文件的<body>中定义了一个用于上传文件的复合表单:
<form action="/TestPro/servlet/UploadServlet"
enctype="multipart/form-data" method="post">
<table>
<tr>
<th><div align="left">User name:</div></th>
<th><input type="text" name="username" /></th>
</tr>
<tr>
<th><div align="left">上传文件一:</div></th>
<th><input type="file" name="file_1" /></th>
</tr>
<tr>
<th><div align="left">上传文件二:</div></th>
<th><input type="file" name="file_2" /></th>
</tr>
<tr>
<th><div align="left">点击提交</div></th>
<th><input type="submit" value="上传提交"/></th>
</tr>
</table>
</form>
上面的html界面效果如下(已选择好了上传文件):
之后是负责上传的Servlet:
【说明】Servlet实现文件的上传需要用到Apache的两个开源软件包(fileupload软件包和io软件包)。
fileupload软件包(commons-fileupload-xxx.jar)可以在下面的链接处下载:
http://commons.apache.org/fileupload/
io软件包(commons-io-xxx.jar)可以在下面的链接处下载:
(两个jar包需要放在WEB-INF下的lib目录中)
【注意】
1.需要注意的是html的正文部分需要设置
enctype="multipart/form-data";
2.使用fileupload来上传文件,会将复合表单中每个子部分看做是一个FileItem,而FileItem的类型有两种:
(1).formField:普通表单域,表单中的文本框或提交按钮;
(2).非formField:上传文件类型,e.g.<input type="file"/>
完整代码如下:
private String filePath; // 文件存储的路径
private String tempFilePath; // 文件的缓存路径
public void init(ServletConfig config) throws ServletException
{
super.init(config);
filePath = config.getInitParameter("filePath");
tempFilePath = config.getInitParameter("tempFilePath");
filePath = getServletContext().getRealPath(filePath);
tempFilePath = getServletContext().getRealPath(tempFilePath);
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doPost(request, response);
}
private void parseFormField(FileItem item, PrintWriter outNet)
{
String name = item.getFieldName();
String value = item.getString();
outNet.println(name + ":" + value);
outNet.println();
}
private void parseUpload(FileItem item, PrintWriter outNet) throws Exception
{
String filename = item.getName();
int index = filename.lastIndexOf("\\");
filename = filename.substring(index + 1, filename.length());
long size = item.getSize();
if (filename.equals("") || size == 0) return;
item.write(new File(filePath + "/" + filename));
outNet.println(filename + " is saved!");
outNet.println("The size of " + filename + " is " + size);
outNet.println();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.setContentType("text/plain");
response.setCharacterEncoding("utf-8");
PrintWriter outNet = response.getWriter();
try
{
DiskFileItemFactory factory = new DiskFileItemFactory();
// setSizeThreshold设置缓存的大小
factory.setSizeThreshold(4 * 1024);
// setRepository设置缓存文件路径
factory.setRepository(new File(tempFilePath));
ServletFileUpload upload = new ServletFileUpload(factory);
// setSizeMax()设置上传文件的最大值
upload.setSizeMax(4 * 1024 * 1024);
//指定fileupload解析FileItem的解码格式
upload.setHeaderEncoding("utf-8");
List items = upload.parseRequest(request);
Iterator itor = items.iterator();
while (itor.hasNext())
{
FileItem item = (FileItem) itor.next();
if (item.isFormField())
{
parseFormField(item, outNet);
} else
{
parseUpload(item, outNet);
}
}
outNet.close();
} catch (Exception e){
}
}
在web.xml中的配置信息如下:
<servlet>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>com.vali.test.UploadServlet</servlet-class>
<init-param>
<param-name>filePath</param-name>
<param-value>store</param-value>
</init-param>
<init-param>
<param-name>tempFilePath</param-name>
<param-value>tmp</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/servlet/UploadServlet</url-pattern>
</servlet-mapping>
最后需要在WEB-ROOT下创建存储文件的文件夹store和缓存文件的文件夹tmp:
点击上传之后的结果如下:
【注意】
为了保证上传文件的中文名显示不出现乱码的情况,要保证浏览器编码格式和服务器解码格式的一致性,浏览器的编码格式在:
在Servlet中通过下面一句来控制fileupload解析FileItem的解码格式: