matrix.boot.common.utils.http.UploadUtil Maven / Gradle / Ivy
package matrix.boot.common.utils.http;
import lombok.extern.slf4j.Slf4j;
import matrix.boot.common.dto.UploadProgressDto;
import matrix.boot.common.dto.UploadResultDto;
import matrix.boot.common.exception.ServiceException;
import matrix.boot.common.utils.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
/**
* 上传工具
*
* @author wangcheng
*/
@Slf4j
public class UploadUtil {
/**
* 文件上传标识
*/
private static final String MULTIPART_FLAG = "multipart";
/**
* 文件路径,后缀名过滤器(分割符|)
*/
private String filePath, suffixFilter;
/**
* 文件最大大小(B)
*/
private Long fileMaxSize;
/**
* 上传servlet
*/
private ServletFileUpload servletFileUpload;
private UploadUtil() {
}
private UploadUtil(String filePath, Long fileMaxSize, String suffixFilter) {
AssertUtil.notNullTip(filePath, "filePath");
AssertUtil.notNullTip(suffixFilter, "suffixFilter");
this.filePath = filePath;
this.fileMaxSize = fileMaxSize;
this.suffixFilter = suffixFilter;
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
servletFileUpload = new ServletFileUpload(diskFileItemFactory);
servletFileUpload.setSizeMax(fileMaxSize);
File cacheDir = new File(filePath + "/cache");
FileUtil.mkdirs(cacheDir.getAbsolutePath());
diskFileItemFactory.setRepository(cacheDir);
diskFileItemFactory.setSizeThreshold(1024 * 2048);
}
/**
* 获取实例
*
* @param filePath 文件路径
* @param fileMaxSize 文件大小(B)
* @param suffixFilter 文件后缀过滤
* @return 上传工具
*/
public static UploadUtil getInstance(String filePath, Long fileMaxSize, String suffixFilter) {
return new UploadUtil(filePath, fileMaxSize, suffixFilter);
}
/**
* 文件上传
*
* @return 上传结果
*/
public Map upload(HttpServletRequest request) {
return upload(request, null);
}
/**
* 文件上传
*
* @return 上传结果
*/
public Map upload(HttpServletRequest request, UploadProgressDto> progress) {
if (!request.getClass().getName().toLowerCase().contains(MULTIPART_FLAG)) {
return uploadNoMultipart(request, progress);
} else {
return uploadMultipart(request);
}
}
/**
* multipart开启后进入
* spring.servlet.multipart.enabled=true
*
* @param request 请求
* @return 上传结果
*/
private Map uploadMultipart(HttpServletRequest request) {
try {
Collection parts = request.getParts();
if (parts != null) {
return upload(parts);
}
} catch (Exception e) {
throw new ServiceException(e);
}
return null;
}
/**
* multipart关闭后进入
* spring.servlet.multipart.enabled=false
*
* @param request 请求体
* @param progress 进度条
* @return 上传结果
*/
private Map uploadNoMultipart(HttpServletRequest request, UploadProgressDto> progress) {
if (!ServletFileUpload.isMultipartContent(request)) {
log.error("ContentType不存在(multipart/form-data)上传失败");
return null;
}
if (progress != null) {
servletFileUpload.setProgressListener(progress);
}
List list;
try {
list = servletFileUpload.parseRequest(request);
} catch (FileUploadException e) {
throw new ServiceException(e);
}
return upload(list);
}
/**
* 上传数据
*
* @param list 列表
* @return 上传结果
*/
private Map upload(Collection> list) {
Map result = new HashMap<>(list.size());
if (CollectionUtils.isEmpty(list)) {
return result;
}
CountDownLatch countDownLatch = new CountDownLatch(list.size());
for (Object item : list) {
//字段名
String fieldName;
//文件名
String fileName;
//文件大小
long fileSize;
if (item instanceof FileItem) {
if (((FileItem) item).isFormField()) {
countDownLatch.countDown();
continue;
}
fieldName = ((FileItem) item).getFieldName();
fileName = ((FileItem) item).getName();
fileSize = ((FileItem) item).getSize();
} else if (item instanceof Part) {
if (((Part) item).getContentType() == null) {
countDownLatch.countDown();
continue;
}
fieldName = ((Part) item).getName();
fileName = ((Part) item).getHeader("content-disposition").split("filename=\"")[1].replaceAll("\"", "");
fileSize = ((Part) item).getSize();
} else {
countDownLatch.countDown();
continue;
}
//后缀名
String suffixName = FileUtil.getSuffix(fileName);
//系统文件名
String sysFileName = RandomUtil.getUUID() + suffixName;
//结果子类
UploadResultDto resultItem = new UploadResultDto(fieldName, fileName, sysFileName);
//校验数据
if (fileSize <= 0) {
resultItem.setMessage("文件大小为0B");
result.put(fieldName, resultItem);
countDownLatch.countDown();
continue;
}
if (fileSize > this.fileMaxSize) {
resultItem.setMessage("文件大于" + this.fileMaxSize + "B");
result.put(fieldName, resultItem);
countDownLatch.countDown();
continue;
}
if (!"*".equals(this.suffixFilter) && !this.suffixFilter.contains(suffixName)) {
resultItem.setMessage("文件类型不在" + this.suffixFilter + "范围内");
result.put(fieldName, resultItem);
countDownLatch.countDown();
continue;
}
ThreadUtil.startThread(() -> {
InputStream is = null;
try {
is = item instanceof FileItem ? ((FileItem) item).getInputStream() : ((Part) item).getInputStream();
BIOStreamUtil.streamWriteFile(is, filePath, sysFileName);
resultItem.setSuccess(true);
result.put(fieldName, resultItem);
} catch (IOException e) {
log.info("No-Multipart:" + e.getMessage());
} finally {
countDownLatch.countDown();
BIOStreamUtil.closeStream(is);
}
});
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
throw new ServiceException(e);
}
return result;
}
}