前言
文件上传下载在类似注册表单中经常会使用到,这里也单独抽取出来,以便日后直接使用。文件上传是以流的方式提交到服务器的,这点与普通的表单提交不同,所以需要对有文件上传域的表单特别声明,这样提交到后台的时候就可以以流的方式进行存取了。实现这个功能我们需要借助Apache的两个jar包:commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar。这两个jar可以在网上直接下载。
文件上传
1、创建一个web工程,并导入上面两个jar包,如下图:
2、创建文件上传表单
<body>
<form action="uploadServlet" enctype="multipart/form-data" method="post">
<h3>文件上传</h3><br>
上传文件1:<input type="file" name="pic1"><br>
上传文件2:<input type="file" name="pic2">
</form>
</body>
3、建立uploadServlet.java文件
package com.rhwayfun.servlet;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class UploadServlet extends HttpServlet {
@SuppressWarnings("unchecked")
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
//1、创建DiskFileItemFactory工厂
FileItemFactory factory = new DiskFileItemFactory();
//2、创建一个文件上传解析器
ServletFileUpload su = new ServletFileUpload(factory);
//解决上传文件名乱码
su.setHeaderEncoding("UTF-8");
List<FileItem> list = null;
//获取输出流对象
PrintWriter out = response.getWriter();
try {
//3、解析Request对象,以便对文件上传域对象进行处理
list= su.parseRequest(request);
for (FileItem fileItem : list) {
if(fileItem.isFormField()){//普通表单域
if(fileItem.getFieldName().equals("username")){
//处理表单提交字段,解决普通输入域中文乱码问题
String username = fileItem.getString("utf-8");
out.print(username + ",");
}
}else{//文件上传域
//得到上传文件的保存目录,将上传的文件保存到WebRoot下的upload文件夹中
String path = this.getServletContext().getRealPath("/WEB-INF/upload");
//浏览器请求路径,这是一个相对路径
String url = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/upload/";
//获取上传文件的文件名
String fileName = fileItem.getName();
//得到上传文件的扩展名
String extName = fileName.substring(fileName.lastIndexOf(".")+1);
//服务器只支持jpg和gif两种格式的文件
if(extName.equals("jpg") || extName.equals("gif")){
File uFile = new File(path);
//如果保存的目录不存在就创建一个目录
if(!uFile.exists()){
uFile.mkdirs();
}
File file = new File(path,fileName);
//写入文件到保存的目录中
fileItem.write(file);
}else{
System.out.println("文件格式不支持");
}
}
}
out.print("上传成功");
} catch (Exception e) {
out.print("对不起,上传失败");
e.printStackTrace();
}
}
}
4、配置web.xml文件
<servlet>
<servlet-name>UploadServlet</servlet-name>
<servlet-class>com.rhwayfun.servlet.UploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadServlet</servlet-name>
<url-pattern>/uploadServlet</url-pattern>
</servlet-mapping>
5、验证是否上传成功
文件下载
实现文件下载需要得到服务器上指定目录下的所有资源,所以第一步是创建一个Servlet用于得到所有的下载资源列表,该Servlet在获取所有资源之后,返回到下载列表的页面,用户可以对其中下载列表进行下载。
首先创建ListFileServlet,用于获取下载资源列表:
package com.rhwayfun.servlet;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ListFileServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//上传文件的时候保存的路径
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
// System.out.println(uploadPath);
//创建一个Map用于保存该目录下的所有文件
Map<String,String> files = new HashMap<String,String>();
//遍历该目录,并保存到该map中
listFileAndSave(new File(uploadPath),files);
//返回给浏览器端
request.setAttribute("files", files);
request.getRequestDispatcher("listFile.jsp").forward(request, response);
}
private void listFileAndSave(File file, Map<String, String> files) {
//首先判断是否是一个目录
if(!file.isFile()){//表示这是一个目录
//得到该目录下的所有文件
File[] fs = file.listFiles();
//遍历列出的所有文件,直到全部都是文件而不是目录为止
for (File file2 : fs) {
listFileAndSave(file2, files);
}
}else{//表示这是一个文件
//需要得到这个文件真实的文件名,比如一个文件为
//D:\apache-tomcat-7.0.42\webapps\\uploadAndDownload\WEB-INF\\upload\c.jpg
//那么其真实的文件名应该是c.jpg才对,所以需要对该文件进行字符串的截取
// System.out.println(file.getPath());
String fileName = file.getPath().substring(file.getPath().lastIndexOf("\\")+1);
files.put(file.getPath(), fileName);
}
}
}
然后配置web.xml文件:
<servlet>
<servlet-name>ListFileServlet</servlet-name>
<servlet-class>com.rhwayfun.servlet.ListFileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ListFileServlet</servlet-name>
<url-pattern>/listFileServlet</url-pattern>
</servlet-mapping>
接着编写listFile.jsp页面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>下载列表</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
</head>
<body>
<form action="">
<c:forEach items="${files }" var="file">
<c:url value="downLoadServlet" var="downurl">
<c:param name="filepath" value="${file.key}"></c:param>
</c:url>
${file.value}<a href="${downurl}">下载</a>
<br>
</c:forEach>
</form>
</body>
</html>
为了防止出错,我们先测试以上代码是否有错:
ok,经过测试,我们的代码是正确的。接下来就要实现下载功能了,首先需要编写DownLoadServlet类,对下载的资源进行处理,请看代码:
package com.rhwayfun.servlet;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DownLoadServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
//获取要下载文件的服务器路径
String filepath = request.getParameter("filepath");
//获取文件名
String filename = filepath.substring(filepath.lastIndexOf("\\")+1);
//设置响应头,控制浏览器下载该文件
response.setContentType("application/x-msdownload");
response.setHeader("Content-disposition", "attachment;filename="+ new String(filename.getBytes("utf-8"), "ISO-8859-1"));
//创建输入流
FileInputStream fis = new FileInputStream(filepath);
//读取文件至缓冲区中
byte[] data = new byte[fis.available()];
fis.read(data);
//关闭流
fis.close();
//创建输出流
OutputStream os = response.getOutputStream();
//写入到文件中
os.write(data);
os.close();
}
}
再配置web.xml文件:
<servlet>
<servlet-name>DownLoadServlet</servlet-name>
<servlet-class>com.rhwayfun.servlet.DownLoadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownLoadServlet</servlet-name>
<url-pattern>/downLoadServlet</url-pattern>
</servlet-mapping>
最后,我们来测试我们的下载功能是否正常:
小结
至此,我们就把文件上传域下载两个功能做完了,实现思路不复杂,主要有一些细节的处理,比如文件名中文乱码问题等。文件上传下载是特别实用的功能,需要介绍的内容也就这么多了。在以后的开发中,直接复用这些代码就很方便了。