本例相关的 jar 包:
/file_demo/WebRoot/WEB-INF/lib/commons-fileupload-1.3.1.jar
/file_demo/WebRoot/WEB-INF/lib/commons-io-2.4-sources.jar
/file_demo/WebRoot/WEB-INF/lib/commons-io-2.4.jar
/file_demo/WebRoot/WEB-INF/lib/commons-lang3-3.1-sources.jar
/file_demo/WebRoot/WEB-INF/lib/commons-lang3-3.1.jar
/file_demo/WebRoot/WEB-INF/lib/jstl.jar
/file_demo/WebRoot/WEB-INF/lib/standard.jar
自定义标签库:
/file_demo/WebRoot/WEB-INF/c.tld
文件上传的 JSP 页面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"
contentType="text/html; charset=UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>图片上载</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
</head>
<body>
<form action="UploadImagesServlet" method="post" enctype="multipart/form-data">
<input type="file" name="image" />
<input type="submit" value="保存" />
</form>
</body>
</html><span style="font-size:18px;">
</span>
文件上传的 UploadImagesServlet :
package com.shanghai.v7.upload;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
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.FileUploadBase;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
/**
* Servlet implementation class uploadImageServlet
*/
public class UploadImagesServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public UploadImagesServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
this.doPost(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
// 响应乱码处理
response.setContentType("text/html;charset=UTF-8");
//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
String path = this.getServletContext().getRealPath("/WEB-INF/upload");
/*ServletContext application = this.getServletContext();
String path = application.getRealPath("uploadImg"); // 要注意如何得到tomcat动态路径
*/
System.out.println(path);
//使用Apache文件上传组件处理文件上传步骤:
//1、创建一个DiskFileItemFactory工厂
FileItemFactory factory = new DiskFileItemFactory();
//2、创建一个文件上传解析器
ServletFileUpload upload = new ServletFileUpload(factory);
//解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
//3、判断提交上来的数据是否是上传表单的数据
if(!ServletFileUpload.isMultipartContent(request)){
//按照传统方式获取数据
return;
}
//设置单个文件的最大限制 5m
upload.setSizeMax(1024*1024*50); // 单位为byte
//消息提示
String message = "";
try {
//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> list = upload.parseRequest(request);// 解析界面中的输入框
for (FileItem fileItem : list) {
//5、如果fileitem中封装的是普通输入项的数据
if (fileItem.isFormField()) { // 普通表单字段
String name = fileItem.getFieldName();
//解决普通输入项的数据的中文乱码问题
String value = fileItem.getString("UTF-8");
//value = new String(value.getBytes("iso8859-1"),"UTF-8");
System.out.println(name + "=" + value);
} else {
//6、如果fileitem中封装的是上传文件
//得到上传的文件名称
String fileName = fileItem.getName();
if(fileName==null || fileName.trim().equals("")){
continue;
}
List<String> fileTypes = Arrays.asList("gif", "bmp", "jpg", "jpeg");// 定义允许上载文件格式
String fileExtName = fileName.substring(fileName.lastIndexOf(".") + 1); // 得到上载文件的后缀名
if (fileTypes.contains(fileExtName)) { // 判断文件类型是否在允许范围内
//按日期生成文件夹
String filedate = FilenameUtils.MONTH_FORMAT.format(new Date());
File file = new File(path+filedate);
//如果文件不存在
if(!file.exists()){
file.mkdirs();
}
String randomName =UUID.randomUUID().toString().replaceAll("-", "");//随机产生32位,为文件名重命名
fileName=randomName+fileName;
//7、流复制到path目录
fileItem.write(new File(file+ File.separator+fileName));
//删除处理文件上传时生成的临时文件
fileItem.delete();
//获取item中的上传文件的输入流
/*InputStream in = null;
BufferedInputStream bis = null;
//创建一个文件输出流
FileOutputStream out = null;
BufferedOutputStream bos = null;
try {
in = fileItem.getInputStream();
bis = new BufferedInputStream(in);
out = new FileOutputStream(path+ File.separator+fileName);
bos = new BufferedOutputStream(out);
//判断输入流中的数据是否已经读完的标识
int len = 0;
//创建一个缓冲区
byte buffer[] = new byte[bis.available()];
//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while((len=bis.read(buffer))>0){
bos.write(buffer, 0, len);
}
} catch (IOException e) {
throw new RuntimeException("IO 异常!");
} finally {
if(bos!=null){
bos.close();
}
if(out!=null){
//关闭输出流
out.close();
}
if(bis!=null){
bis.close();
}
if(in!=null){
//关闭输入流
in.close();
}
if(fileItem!=null){
//删除处理文件上传时生成的临时文件
//fileItem.delete();
}
}*/
message = "文件上传成功!";
} else {
message = "上传失败,文件类型只能是gif、bmp、jpg、jpeg";
}
}
}
} catch (FileUploadBase.SizeLimitExceededException e) {
message = "上传失败,文件太大,单个文件的最大限制是:" + upload.getSizeMax() + " byte! ;实际上载文件的大小为: ";
} catch (Exception e) {
message= "文件上传失败!";
e.printStackTrace();
}
request.setAttribute("message",message);
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
}
文件名生成帮助类:
package com.shanghai.v7.upload;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang3.RandomStringUtils;
/**
* @Description: 文件名生成帮助类
* @author
* @date 2014-11-13 下午04:31:01
* @version V1.0
*/
public abstract class FilenameUtils {
/**
* 日期格式化对象,将当前日期格式化成yyyyMM格式,用于生成目录。
*/
public static final DateFormat pathDf = new SimpleDateFormat("yyyyMM");
/**
* 日期格式化对象,将当前日期格式化成ddHHmmss格式,用于生成文件名。
*/
public static final DateFormat nameDf = new SimpleDateFormat("ddHHmmss");
/**
* 36个小写字母和数字
*/
public static final char[] N36_CHARS = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z' };
public static final DateFormat MONTH_FORMAT = new SimpleDateFormat("/yyyyMM/dd");
/**
* 生成当前年月格式的文件路径
*
* yyyyMM 200806
*
* @return
*/
public static String genPathName() {
return pathDf.format(new Date());
}
/**
* 生产以当前日、时间开头加4位随机数的文件名
*
* ddHHmmss 03102230
*
* @return 10位长度文件名
*/
public static String genFileName() {
return nameDf.format(new Date()) + RandomStringUtils.random(4, N36_CHARS);
}
/**
*
* @Description: 根据文件路径及后缀名产生文件名 如/base/201412/10082804aia5.gif
* @author
* @date 2014-12-10 上午08:27:02
* @version V1.0
*/
public static File generateFilename(File path, String ext) {
String fileName= RandomStringUtils.random(4, FilenameUtils.N36_CHARS) + "." + ext;
return new File(path,fileName);
}
/**
* 生产以当前时间开头加4位随机数的文件名
*
* @param ext
* 文件名后缀,不带'.'
* @return 10位长度文件名+文件后缀
*/
public static String genFileName(String ext) {
return genFileName() + "." + ext;
}
/**
*
* @Description: 获得文件的后缀名
* @author
* @param fileName
* 文件名
* @date 2014-11-13 下午04:32:24
* @version V1.0
*/
public static String getFileSufix(String fileName) {
int splitIndex = fileName.lastIndexOf(".");
return fileName.substring(splitIndex + 1);
}
public static void main(String[] args) {
System.out.println(genPathName());
System.out.println(genFileName());
}
}
跳转 文件 列表 的ListFileServlet:
package com.shanghai.v7.downlad;
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;
@SuppressWarnings("serial")
public class ListFileServlet extends HttpServlet {
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to
* post.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//System.out.println("======================>");
// 获取上传文件的目录
String uploadFilePath = this.getServletContext().getRealPath("/WEB-INF/upload");
// 存储要下载的文件名
Map<String, String> fileNameMap = new HashMap<String, String>();
// 递归遍历filepath目录下的所有文件和目录,将文件的文件名存储到map集合中
listfile(new File(uploadFilePath), fileNameMap);// File既可以代表一个文件也可以代表一个目录
// 将Map集合发送到listfile.jsp页面进行显示
request.setAttribute("fileNameMap", fileNameMap);
request.getRequestDispatcher("/listfile.jsp").forward(request, response);
}
public void listfile(File file, Map<String, String> map) {
// 如果file代表的不是一个文件,而是一个目录
if (!file.isFile()) {
// 列出该目录下的所有文件和目录
File files[] = file.listFiles();
// 遍历files[]数组
for (File f : files) {
// 递归
listfile(f, map);
}
} else {
/**
* 处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分
* file.getName().indexOf("_")检索字符串中第一次出现"_"字符的位置,如果文件名类似于:9349249849-88343-8344_阿_凡_达.avi
* 那么file.getName().substring(file.getName().indexOf("_")+1)处理之后就可以得到阿_凡_达.avi部分
*/
String realName = file.getName().substring(file.getName().indexOf("_") + 1);
// file.getName()得到的是文件的原始名称,这个名称是唯一的,因此可以作为key,realName是处理过后的名称,有可能会重复
map.put(file.getName(), realName);
}
}
}
上传后文件列表界面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML>
<html>
<head>
<title>下载文件显示页面</title>
</head>
<body>
<!-- 遍历Map集合 -->
<c:forEach var="me" items="${fileNameMap}">
<c:url value="/DownLoadServlet" var="downurl">
<c:param name="filename" value="${me.key}"></c:param>
</c:url>
<img src="${downurl}" width="150px" height="100px" />
${me.value}<a href="${downurl}">下载</a>
<br />
</c:forEach>
</body>
</html>
下载的DownLoadServlet:
package com.shanghai.v7.downlad;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.shanghai.v7.upload.FilenameUtils;
public class DownLoadServlet extends HttpServlet {
/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
/**
* The doPost method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to
* post.
*
* @param request
* the request send by the client to the server
* @param response
* the response send by the server to the client
* @throws ServletException
* if an error occurred
* @throws IOException
* if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 得到要下载的文件名
String fileName = request.getParameter("filename");
//System.out.println(fileName);
fileName = new String(fileName.getBytes("iso8859-1"), "UTF-8");
// 上传的文件都是保存在/WEB-INF/upload目录下的子目录当中
String fileSaveRootPath = this.getServletContext().getRealPath("/WEB-INF/upload");
// 通过文件名找出文件的所在目录
String path = findFileSavePathByFileName(fileName, fileSaveRootPath);
// 得到要下载的文件
File file = new File(path + "\\" + fileName);
// 如果文件不存在
if (!file.exists()) {
request.setAttribute("message", "您要下载的资源已被删除!!");
request.getRequestDispatcher("/message.jsp").forward(request,
response);
return;
}
// 处理文件名
String realname = fileName.substring(fileName.indexOf("_") + 1);
// 设置响应头,控制浏览器下载该文件
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
// 读取要下载的文件,保存到文件输入流
FileInputStream in = new FileInputStream(path + "\\" + fileName);
// 创建输出流
OutputStream out = response.getOutputStream();
// 创建缓冲区
byte buffer[] = new byte[1024];
int len = 0;
// 循环将输入流中的内容读取到缓冲区当中
while ((len = in.read(buffer)) > 0) {
// 输出缓冲区的内容到浏览器,实现文件下载
out.write(buffer, 0, len);
}
// 关闭文件输入流
in.close();
// 关闭输出流
out.close();
}
public String findFileSavePathByFileName(String filename,
String saveRootPath) {
/*int hashcode = filename.hashCode();
System.out.println(hashcode);
int dir1 = hashcode & 0xf; // 0--15
int dir2 = (hashcode & 0xf0) >> 4; // 0-15
String dir = saveRootPath + "\\" + dir1 + "\\" + dir2; // upload\2\3
// upload\3\5
File file = new File(dir);
if (!file.exists()) {
// 创建目录
file.mkdirs();
}*/
String filedate = FilenameUtils.MONTH_FORMAT.format(new Date());
String dir = saveRootPath+filedate;
return dir;
}
}
message.jsp :
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>message</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="description" content="This is my page">
<script type="text/javascript" src="jquery.js"></script>
</head>
<body>
<h1>${message}</h1>
<a href="${pageContext.request.contextPath}/servlet/ListFileServlet">下载</a>
</body>
</html>