同样,其中涉及到的jar包
使用前面的文件上传的界面,可以使用这一版
这里就只贴servlet中的代码了,关于一些解释,全在代码的注释中了:
package upload;
import java.io.File;
import java.io.IOException;
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.FileUploadBase.FileSizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import exception.FileTypeErrorException;
/**
* 文件上传!细节注意:
* 1.限制单文件的大小
* 2.限制总文件的大小
* 3.限制文件的类型
* 4.解决之前的文件同名覆盖的问题
* 5.在file下生成有规律有意义,可查找或者安全的目录。
*
* 使用apache的文件上传和下载的组件
* 1.导入jar包
* commons-fileload-1.2.2.jar
* commons-io-2.1.jar 一个IO流工具(更方便)
* @author mzy
*
*/
public class UpLoadDemo04 extends HttpServlet {
private static final long serialVersionUID = 987003232758385500L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
DiskFileItemFactory factory = new DiskFileItemFactory(10*1024, new File("e:/temp"));
ServletFileUpload upload = new ServletFileUpload(factory);
/*
* 注册一个文件监听器:
* 监听上传的进度!
*/
upload.setProgressListener(new MyProgressListener());
upload.setHeaderEncoding("utf-8");
/*
* 注意限制文件大小的两个方法:
* setFileSizeMax(100*1024):单个文件大小不超过100KB
* setSizeMax(300*1024):文件总大小不超过300KB
*/
// 一个request中最大的容量为300KB
upload.setSizeMax(300*1024);
// 单个文件的最大容量为100KB
upload.setFileSizeMax(100*1024);
// 解析request
List<FileItem> list = upload.parseRequest(request);
if(list != null) {
for(FileItem item: list) {
/*
* 注意:
* 限制文件的类型。文件的
* 类型(mime-type):image/*
* 只能上传图片
*/
// 得到文件的类型
String contentType = item.getContentType();
if(!contentType.contains("image/")) {
throw new FileTypeErrorException("文件类型错误,请换一张图片!");
}
/*
* 使用UUID算法,生成唯一的文件名
* 避免文件覆盖的问题!
*/
String uuid = UUID.randomUUID().toString();
// get到真正的文件名!
/*
* 这里我们就不用做兼容性的处理了
* 因我们只用get一个LastIndexOf(".")
* 去获得文件的后缀名,保证文件能够正常的打开!
*/
String fileName = item.getName();
// 获取到后缀名
fileName = fileName.substring(fileName.lastIndexOf("."));
// 组合新的文件名
String newFileName = uuid+fileName;
// 得到新的目录结构
String dir = "e:/files/"+makeDirectory(newFileName);
// 生成目录结构
File file = new File(dir);
// 如果不存在这个目录结构!
if(!file.exists()) {
file.mkdirs();
// mkdir只能生成单个目录,所以要用mkdirs
}
//开始文件传输
FileUtils.copyInputStreamToFile(item.getInputStream(), new File(dir+newFileName));
// 删除item传输的tmp临时文件
item.delete();
}
}
} catch (FileTypeErrorException e) {
// 捕获文件类型异常
request.setAttribute("msg", e.getMessage());
request.getRequestDispatcher("/04.upload.jsp").forward(request, response);
} catch (FileSizeLimitExceededException e) {
// 捕获单个文件大小超规定范围异常
request.setAttribute("msg", "单个文件超过设定大小:100KB");
request.getRequestDispatcher("/04.upload.jsp").forward(request, response);
} catch (SizeLimitExceededException e) {
// 捕获总文件大小超规定范围异常
request.setAttribute("msg", "总文件超过设定大小:300KB");
request.getRequestDispatcher("/04.upload.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 思考,生成有意义的目录结构:
*
* 第一种三层结构: 年-月-日
*
*
* 第二种两层结构:通过hashcode生成的更安全的随机目录
* 动态生成新的目录结构:
* (第一级目录)/(第二级目录)
* @return 新的目录结构:右边是带斜杠的(左边不带),
* 可直接进行字符串拼接
*/
private String makeDirectory(String fileName) {
// 1.得到文件名的hashCode
int code = fileName.hashCode();
// 2.算出第一层目录的名称
// 第一层目录的数字大小不会超过15
int first = code & 0xF; // 十六进制的15
// 3.算出第二层目录的名称:先右移一位
int second = code & (0xF >> 1);
return first+"/"+second+"/";
}
/**
* 实现ProgressListener监听文件上传进度
*/
class MyProgressListener implements ProgressListener {
/*
* 参数1:目前上传了多少字节
* 参数2:总长度
* 参数3:目前正在第几个文件
*/
@Override
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("正在上传第"+pItems+"个文件!");
System.out.println("已经上传了"+pBytesRead+"字节"+",总字节为"+pContentLength+"字节");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
doGet(request, response);
}
}