文件上传、下载封装
FileUtils
package com.test.common.utils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.test.common.utils.file.FileType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
public abstract class FileUtils {
private static final Logger log = LoggerFactory.getLogger(FileUtils.class);
public static String upload(String dirPath, MultipartFile uploadFile, boolean createFlag) throws IOException {
Assert.isTrue(StrUtil.isNotEmpty(dirPath), "dirPath不能为空");
Assert.isTrue(ObjectUtil.isNotNull(uploadFile), "file不能为空");
String originalFilename = uploadFile.getOriginalFilename();
String[] strs = originalFilename.split(".");
String suffix = strs[strs.length - 1];
FileType fileType = FileType.getBySuffixName(suffix);
if(!isNormative(fileType, uploadFile.getBytes())) {
throw new IllegalArgumentException(String.format("文件内容与文件类型不匹配"));
}
String chineseChar = hasChinese(dirPath);
Assert.isTrue(StrUtil.isEmpty(chineseChar),String.format("dirPath包含中文字符[%s]",chineseChar));
final String tempPath = dirPath;
String osName = SystemUtils.judgeSystem();
SystemUtils.SystemType[] systemTypes = SystemUtils.SystemType.values();
boolean matchResult = Arrays.stream(systemTypes).filter(systemType -> !systemType.getTypeName().equalsIgnoreCase(osName))
.anyMatch(systemType -> tempPath.contains(systemType.getFileSeparator()));
if(matchResult) {
throw new IllegalArgumentException("dirPath中包含不属于当前操作系统的路径分隔符");
}
dirPath = dirPath + (dirPath.endsWith(File.separator) ? "" : File.separator);
File file = new File(dirPath);
boolean isExists = file.exists();
if(isExists) {
if(!file.isDirectory()) {
throw new IllegalArgumentException(String.format("存在%s,但是类型不是目录",dirPath));
}
} else {
if(!createFlag) {
throw new IllegalArgumentException(String.format("目标路径[%s]不存在",dirPath));
}
boolean mkResult = file.mkdir();
if(!mkResult) {
throw new RuntimeException(String.format("目录[%s]创建失败",dirPath));
}
}
String newFileName = "TEST_UPLOAD" + uploadFile.getOriginalFilename() + DateUtil.format(new Date(), "yyyy-MM-dd") + UUID.randomUUID();
String newFileFullName = dirPath + newFileName;
ByteBuffer buffer = ByteBuffer.allocate(10240);
ReadableByteChannel readChannel = Channels.newChannel(uploadFile.getInputStream());
File newFile = new File(newFileFullName);
if(!newFile.exists()) {
if(!newFile.createNewFile()) {
throw new RuntimeException(String.format("文件[%s]创建失败"));
}
}
FileChannel writeChannel = new FileOutputStream(newFile).getChannel();
while (readChannel.read(buffer) != -1) {
buffer.flip();
writeChannel.write(buffer);
buffer.clear();
}
writeChannel.close();
readChannel.close();
return newFileFullName;
}
public static boolean isNormative(FileType fileType, byte[] bytes) {
List<String> magicNumbers = fileType.getMagicNumbers();
int[] magicNumberLength = fileType.getMagicNumberLength();
for(int i = 0;i < magicNumberLength.length; i++) {
int contentLength = magicNumberLength[i];
byte[] content = new byte[contentLength];
for(int j = 0;j < contentLength;j++) {
content[j] = bytes[j];
}
StringBuilder stringBuilder = new StringBuilder();
for(int j=0;j<content.length;j++) {
int val = content[j] & 0XFF;
String hexVal = Integer.toHexString(val);
if(hexVal.length() < 2) {
stringBuilder.append("0");
}
stringBuilder.append(hexVal);
}
if(!stringBuilder.toString().equals(magicNumbers.get(i))) {
return false;
}
}
return true;
}
public static String hasChinese(String path) {
Assert.isTrue(StrUtil.isNotEmpty(path),"path不能为空");
char[] charArr = path.toCharArray();
for(int i = 0; i<charArr.length; i++) {
char val = charArr[i];
if(((int)val) > 127) {
return String.valueOf(val);
}
}
return null;
}
}
FileType
package com.test.common.utils.file;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.util.Assert;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public enum FileType {
JPEG("JPEG", Stream.of("FFD8FF").collect(Collectors.toList()), new int[]{3},Stream.of(".jpg",".jpeg",".jpe",".jfif",".exif").collect(Collectors.toList())),
PNG("PNG",Stream.of("89504E470D0A1A0A").collect(Collectors.toList()), new int[]{8},Stream.of(".png").collect(Collectors.toList())),
GIF("GIF",Stream.of("474946383961","4749383761").collect(Collectors.toList()), new int[]{6,6},Stream.of(".gif").collect(Collectors.toList())),
BMP("BMP",Stream.of("424D").collect(Collectors.toList()), new int[]{2},Stream.of(".bmp",".dib").collect(Collectors.toList())),
TIFF("TIFF",Arrays.asList("4D4D002A","49492A00"),new int[]{4,4},Arrays.asList(".tif",".tiff")),
WORD("WORD",Arrays.asList("D0CF11E0A1B11AE1"),new int[]{8},Arrays.asList(".doc")),
WORD_XML("WORD_XML",Arrays.asList("504B0304"),new int[]{4},Arrays.asList(".docx",".docm",".dotx",".dotm")),
PPT("PPT",Arrays.asList("D0CF11E0A1B11AE1"),new int[]{8},Arrays.asList(".ppt")),
PPT_XML("PPT_XML",Arrays.asList("504B0304"),new int[]{4},Arrays.asList(".pptx",".pptm",".potx",".potm")),
EXCEL("EXCEL",Arrays.asList("D0CF11E0A1B11AE1"),new int[]{8},Arrays.asList(".xls")),
EXCEL_XML("EXCEL_XML",Arrays.asList("504B030414000600"),new int[]{8},Arrays.asList(".xlsx",".xlsm",".xlsb",".xltx")),
EXCEL_XLT("EXCEL_XLT",Arrays.asList("D0CF11E0A1B11AE1"),new int[]{8},Arrays.asList(".xlt")),
TXT("TXT",Arrays.asList(".txt",".text"));
private String fileType;
private List<String> magicNumbers;
private int[] magicNumberLength;
private List<String> suffixNames;
FileType(String fileType, List<String> magicNumbers, int[] magicNumberLength, List<String> suffixNames) {
Assert.isTrue(StrUtil.isNotEmpty(fileType),"fileType不能为空");
Assert.isTrue(CollUtil.isNotEmpty(magicNumbers),"magicNumbers不能为空");
Assert.isTrue(null != magicNumberLength && magicNumberLength.length > 0 && magicNumberLength.length == magicNumbers.size(),
"magicNumberLength不能为空且长度必须等于magicNumbers的个数");
Assert.isTrue(CollUtil.isNotEmpty(suffixNames),"suffixNames不能为空");
this.fileType = fileType;
this.magicNumbers = magicNumbers;
this.magicNumberLength = magicNumberLength;
this.suffixNames = suffixNames;
}
FileType(String fileType, List<String> suffixNames) {
Assert.isTrue(StrUtil.isNotEmpty(fileType),"fileType不能为空");
Assert.isTrue(CollUtil.isNotEmpty(suffixNames),"suffixNames不能为空");
this.fileType = fileType;
this.suffixNames = suffixNames;
}
public String getFileType() {
return fileType;
}
public List<String> getMagicNumbers() {
return magicNumbers;
}
public int[] getMagicNumberLength() {
return magicNumberLength;
}
public List<String> getSuffixNames() {
return suffixNames;
}
public static FileType getBySuffixName(String fileSuffixName) {
if(!isSupported(fileSuffixName)) {
throw new IllegalArgumentException(String.format("暂不支持处理该类型的文件[%s]",fileSuffixName));
}
FileType[] arr = values();
List<FileType> fileTypeList = Arrays.stream(arr).filter(val->val.suffixNames.contains(fileSuffixName)).collect(Collectors.toList());
if(fileTypeList.size() > 1) {
throw new IllegalArgumentException(String.format("文件类型存在错误[%s]",fileSuffixName));
}
return fileTypeList.get(0);
}
public static boolean isSupported(String fileSuffixName) {
FileType[] arr = values();
return Arrays.stream(arr).anyMatch(val->val.suffixNames.contains(fileSuffixName));
}
}