自己封装文件上传
- 需要的jar包
- 文件上传的几大要素
- 构建文件上传构造方法
- 文件上传的执行流程
- 前端页面文件提交
- 服务端的处理
需要的jar包
commons-fileupload-1.3.1.jar
commons-io-2.2.jar
导入了这两个包就可以用java进行文件上传了
文件上传的几大要素
- 上传的目标路径(就是要上传到服务器的那个目录)
- 需要有文件名 (有时需要生成随机id标识)
- 文件大小限制
- 文件类型限制
- 文件上传过程中的临时文件夹
- 文件上传过程中的内存缓存大小
我们可以将以上的几个属性封装成为类属性
private static final String DEFAULT_TEMP_FILEPATH = "D:\\temp\\buffer\\";//默认临时路径
private static final String[] DEFAULT_FILETYPE = { "jpg", "png", "bmp", "gif"};//默认上传的文件类型
private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 4;//默认缓存大小4k
private static final int DEFAULT_SIZE_MAX = 1024 * 5000;//默认最大文件大小5mb
private String fileLoadPath; //上传目标的路径
private String fileName; //文件名
private String tempFilePath; //临时文件夹
private String[] fileType; //允许的文件类型
private int sizeThreshold; //上传缓存区大小
private int sizeMax; //上传文件最大大小限制
private DiskFileItemFactory factory; //磁盘文件工厂
private ServletFileUpload upload; //文件上传对象
前属性为默认值。
构建文件上传构造方法
我们进行文件上传是肯定要使用上面这个对象进行操作,那么我们得在这个对象实例化的时候做一些事情,比如初始化一些重要参数:
第一个构造方法:
public FileLoadUtil(String loadPath, String tempFilePath, String[] fileType, int sizeThreshold, int sizeMax) {
this.fileLoadPath = loadPath; //上传的目标路径
this.tempFilePath = tempFilePath; //临时文件夹
this.fileType = fileType; //指定文件类型
this.sizeThreshold = sizeThreshold; //缓存大小
this.sizeMax = sizeMax; //文件最大允许大小
}
第二个构造方法:
public FileLoadUtil(String loadPath) {
this.tempFilePath = DEFAULT_TEMP_FILEPATH; //设置默认的临时路径
this.fileType = DEFAULT_FILETYPE; //设置默认运行的文件类型
this.sizeThreshold = DEFAULT_SIZE_THRESHOLD; //设置默认的缓存大小
this.sizeMax = DEFAULT_SIZE_MAX; //设置默认的最大文件允许大小
this.fileLoadPath = loadPath; //设值文件上传目标路径
this.factory = new DiskFileItemFactory(); //实例化磁盘文件工厂对象
}
第三个:
public FileLoadUtil(){
}
接下来就是一些get 和 set的方法的定义了,这里不会列出,后面会一起把完整的代码列出来。
文件上传的执行流程
我将此执行流程分为一个个的方法,每个方法都作为一个模块,这样可以方便以后扩展和维护。
- 先创建临时文件夹
public boolean createTempDirectory() {
File tempPatchFile = new File("D:\\temp\\buffer\\");
//检查目录是否存在
if (!tempPatchFile.exists()) {
//创建该目录
if (!tempPatchFile.mkdirs()) {
return false;
}
}
return true;
}
- 设置文件上传参数
public void setUploadParam() {
//设置缓存大小
factory.setSizeThreshold(sizeThreshold);
//设置临时文件夹
factory.setRepository(new File(tempFilePath));
//实例化文件上传对象
upload = new ServletFileUpload(factory);
//设置上传文件最大大小
upload.setSizeMax(sizeMax);
}
- 处理请求的文件集合
public List<String> processFormFile(List<FileItem> fileItems) throws Exception {
//存放文件名的集合
List<String> nameArr = new ArrayList<>();
//用于迭代遍历fileItems
Iterator<FileItem> itemIterator = fileItems.iterator();
//遍历fileItems集合
while (itemIterator.hasNext()) {
//获取List<FileItem>集合中的每一个FileItem项
FileItem fileItem = itemIterator.next();
//判断该表单是否为file类型(file:false,nofile:true)
if (!fileItem.isFormField()) {
String name;
//此处上传单个文件
if((name = fileUploading(fileItem)) != null)
//将文件名保存至集合
nameArr.add(name);
}
}
return nameArr;
}
- 文件上传主要实现
private String fileUploading(FileItem fileItem) throws Exception {
String fileName = fileItem.getName();
//将文件类型数组转换为ArrayList集合
List<String> fileType = Arrays.asList(this.fileType);
//获取文件后缀名
String ext = fileName.substring(fileName.lastIndexOf(".") + 1);
//如果不匹配返回true
if (!fileType.contains(ext)) {
System.out.println("文件类型不符合");
} else {
//文件名不能为空和空字符
if (fileName != null && !fileName.equals("")) {
//目标文件对象
File fullFile = new File(fileName);
//上传路径对象
File fileSave = new File(fileLoadPath, fullFile.getName());
//将文件上传
fileItem.write(fileSave);
//返回文件名
return fileName;
}
}
return null;
}
以上4个方法就可以实现多文件上传了,接下来只剩下一个主调方法来将以上的流程组合起来:
public List<String> defUpload(HttpServletRequest req) throws Exception{
//先创临时文件夹
if(!this.createTempDirectory()){
System.out.println("创建文件夹失败");
}
//设置文件上传参数
this.setUploadParam();
List<FileItem> fileItems = null;
//判断是否为文件上传表单
if(ServletFileUpload.isMultipartContent(req)) {
//从请求中获取文件集合
fileItems = upload.parseRequest(req);
//返回文件上传后的文件名称集合
return this.processFormFile(fileItems);
}
return null;
}
至此这个类已经写好了。
前端页面文件提交
我们通常有两种方式提交文件,一个是通过form表单提交,一个是通过ajax异步提交,那么在这个案例中,我将通过使用ajax来提交文件。
<input type = "file"/>
<input type = "file"/>
<input type = "file"/>
<button id = "cli">上传</button>
上面我定义了几个input标签,类型文文件类型,其中没有用到form表单。当我点击上传按钮的时候就会将这三个标签中的文件上传至服务器。
以下是我的js代码,利用了jquery的ajax:
$("#cli").click(function(){
var form = new FormData();
var fileobjs = new Array();
for(var i = 0; i < $("input[type='file']").length; i++) {
var ele = document.getElementsByTagName("input");
fileobjs[i] = ele[i].files[0]
}
for(var i = 0; i < fileobjs.length; i++) {
form.append("img", fileobjs[i]);
}
fileUpload(form)
})
上面是获取input中的文件并封装到FormData的一个过程,然后再将form中的数据交给fileUpload提交到服务器上传。
现在看看fileUpload方法:
function fileUpload(form) {
$.ajax({
type:"post",
async:false,
url:"/MyFileUpload/file",
data:form,
dataType:"text",
processData : false, // 使数据不做处理
contentType : false, // 不要设置Content-Type请求头
success:function (data) {
},
error:function(){
alert("FBI Waring")
}
})
}
我们在这里要加上这两个属性设置 processData : false, contentType : false,这样请求到服务器是就不会是个对象了,保证了数据的可上传性。
服务端的处理
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//文件上传的工具类
FileLoadUtil fileLoadUtil = new FileLoadUtil("D:/img");
try {
//获取到成功上传的文件集合
List<String> list = fileLoadUtil.defUpload(req);
if (list != null) {
for (String string : list) {
System.out.println(string + "已成功上传...");
}
System.out.println(list.size()+"个文件已成功上传");
} else {
System.out.println("上传失败");
}
} catch (Exception e) {
e.printStackTrace();
}
}
最后我把封装好的工具类奉上,如果是初学可以参考一下,尝试自己改变其中的定义,让他变得更好:
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class FileLoadUtil {
private static final String DEFAULT_TEMP_FILEPATH = "D:\\temp\\buffer\\";//默认临时路径
private static final String[] DEFAULT_FILETYPE = { "jpg", "png", "bmp", "gif"};//默认上传的文件类型
private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 4;//默认缓存大小4k
private static final int DEFAULT_SIZE_MAX = 1024 * 5000;//默认最大文件大小5mb
private String fileLoadPath; //上传目标的路径
private String fileName; //文件名
private String tempFilePath; //临时文件夹
private String[] fileType; //允许的文件类型
private int sizeThreshold; //上传缓存区大小
private int sizeMax; //上传文件最大大小限制
private DiskFileItemFactory factory; //磁盘文件工厂
private ServletFileUpload upload; //文件上传对象
public FileLoadUtil(String loadPath, String tempFilePath, String[] fileType, int sizeThreshold, int sizeMax) {
this.fileLoadPath = loadPath;
this.tempFilePath = tempFilePath;
this.fileType = fileType;
this.sizeThreshold = sizeThreshold;
this.sizeMax = sizeMax;
}
public FileLoadUtil(String loadPath) {
this.tempFilePath = DEFAULT_TEMP_FILEPATH;
this.fileType = DEFAULT_FILETYPE;
this.sizeThreshold = DEFAULT_SIZE_THRESHOLD;
this.sizeMax = DEFAULT_SIZE_MAX;
this.fileLoadPath = loadPath;
this.factory = new DiskFileItemFactory();
}
public FileLoadUtil(){
}
public static String getDefaultTempFilepath() {
return DEFAULT_TEMP_FILEPATH;
}
public String getFileLoadPath() {
return fileLoadPath;
}
public void setFileLoadPath(String fileLoadPath) {
this.fileLoadPath = fileLoadPath;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getTempFilePath() {
return tempFilePath;
}
public void setTempFilePath(String tempFilePath) {
this.tempFilePath = tempFilePath;
}
public String[] getFileType() {
return fileType;
}
public void setFileType(String[] fileType) {
this.fileType = fileType;
}
public int getSizeThreshold() {
return sizeThreshold;
}
public void setSizeThreshold(int sizeThreshold) {
this.sizeThreshold = sizeThreshold;
}
public int getSizeMax() {
return sizeMax;
}
public void setSizeMax(int sizeMax) {
this.sizeMax = sizeMax;
}
public boolean createTempDirectory() {
File tempPatchFile = new File("D:\\temp\\buffer\\");
//检查目录是否存在
if (!tempPatchFile.exists()) {
//创建该目录
if (!tempPatchFile.mkdirs()) {
return false;
}
}
return true;
}
public void setUploadParam() {
//设置缓存大小
factory.setSizeThreshold(sizeThreshold);
//设置临时文件夹
factory.setRepository(new File(tempFilePath));
//实例化文件上传对象
upload = new ServletFileUpload(factory);
//设置上传文件最大大小
upload.setSizeMax(sizeMax);
}
public List<String> processFormFile(List<FileItem> fileItems) throws Exception {
//存放文件名的集合
List<String> nameArr = new ArrayList<>();
//用于迭代遍历fileItems
Iterator<FileItem> itemIterator = fileItems.iterator();
//遍历fileItems集合
while (itemIterator.hasNext()) {
//获取List<FileItem>集合中的每一个FileItem项
FileItem fileItem = itemIterator.next();
//判断该表单是否为file类型(file:false,nofile:true)
if (!fileItem.isFormField()) {
String name;
//此处上传单个文件
if((name = fileUploading(fileItem)) != null)
//将文件名保存至集合
nameArr.add(name);
}
}
return nameArr;
}
private String fileUploading(FileItem fileItem) throws Exception {
String fileName = fileItem.getName();
//将文件类型数组转换为ArrayList集合
List<String> fileType = Arrays.asList(this.fileType);
//获取文件后缀名
String ext = fileName.substring(fileName.lastIndexOf(".") + 1);
//如果不匹配返回true
if (!fileType.contains(ext)) {
System.out.println("文件类型不符合");
} else {
//文件名不能为空和空字符
if (fileName != null && !fileName.equals("")) {
//目标文件对象
File fullFile = new File(fileName);
//上传路径对象
File fileSave = new File(fileLoadPath, fullFile.getName());
//将文件上传
fileItem.write(fileSave);
//返回文件名
return fileName;
}
}
return null;
}
public List<String> defUpload(HttpServletRequest req) throws Exception{
//先创临时文件夹
if(!this.createTempDirectory()){
System.out.println("创建文件夹失败");
}
//设置文件上传参数
this.setUploadParam();
List<FileItem> fileItems = null;
//判断是否为文件上传表单
if(ServletFileUpload.isMultipartContent(req)) {
//从请求中获取文件集合
fileItems = upload.parseRequest(req);
//返回文件上传后的文件名称集合
return this.processFormFile(fileItems);
}
return null;
}
}
其端页面很灵活,可以自己动手制作