package com.topsports.decision.engine.common.core.util;
import com.topsports.decision.engine.common.core.exception.BizException;
import okhttp3.*;
import org.apache.tika.metadata.HttpHeaders;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.metadata.TikaMetadataKeys;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import org.xml.sax.helpers.DefaultHandler;
import ws.schild.jave.MultimediaObject;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
/**
* @author yukun.yan
* @description FileUploadUtils 目标文件根据自定义规则校验
* @date 2023/5/17 14:48
*/
public class FileUploadUtils {
private FileUploadUtils() {
throw new UnsupportedOperationException();
}
/**
* 初始化文件解析器
*/
private static final AutoDetectParser parser = new AutoDetectParser();
private static final ParseContext parseContext = new ParseContext();
/**
* 判断上传的图片文件像素是否超过指定值
*
* @param file MultipartFile对象
* @param maxPixels 最大像素值
* @return true 表示图片像素没有超过指定值,false表示图片像素超过了指定值maxPixels
*/
public static boolean isImagePixelExceeded(MultipartFile file, int maxPixels) {
try (InputStream inputStream = file.getInputStream()) {
BufferedImage image = ImageIO.read(inputStream);
AssertUtils.notNull(image, BizException.biz("Invalid image file"));
int width = image.getWidth();
int height = image.getHeight();
int pixels = width * height;
return pixels < maxPixels;
} catch (Exception e) {
throw BizException.biz(e.getMessage());
}
}
/**
* 判断上传的视频文件时长是否超过指定值
*
* @param multipartFile 文件
* @param maxDurationSecond 最大支持的视频时长(秒)
* @return 不超过指定的秒数返回true
*/
public static boolean isVideoDurationExceeded(MultipartFile multipartFile, int maxDurationSecond) {
try {
// 创建临时文件夹, 会自动删除
File tempFile = File.createTempFile("temp", null);
// 拷贝
multipartFile.transferTo(tempFile);
MultimediaObject multimediaObject = new MultimediaObject(tempFile);
long durationMillisecond = multimediaObject.getInfo().getDuration();
// 手动删除
tempFile.delete();
return durationMillisecond < maxDurationSecond * 1000L;
} catch (Exception e) {
throw BizException.biz(e.getMessage());
}
}
/**
* 判断上传的文件大小是否超过指定值
*
* @param file 文件
* @param maxSizeMb 文件最大大小
* @return 没有超过指定值maxSize, 返回true
*/
public static boolean isSizeExceeded(MultipartFile file, long maxSizeMb) {
if (!isFileExist(file)) {
throw BizException.biz("File does not exist");
}
long size = file.getSize();
// 没有超过指定值
return size < (maxSizeMb * 1024 * 1024);
}
/**
* 校验文件类型是不是我们预期的类型
*
* @param file 文件
* @param expectedMimeTypes 预期的文件类型的Pattern, 可以自定义任意文件类型
* @return 不匹配, 返回false
*/
public static boolean isFileTypeMatch(MultipartFile file, List<Pattern> expectedMimeTypes) {
// 获取文件类型
String fileType = getFileRealType(file);
for (Pattern expectedMimeType : expectedMimeTypes) {
if (expectedMimeType.matcher(fileType).matches()) {
return true;
}
}
return false;
}
/**
* 获取文件类型, 根据文件后缀名判断无法准确判断类型
*
* @param file
* @return
*/
public static String getFileRealType(MultipartFile file) {
Metadata metadata = new Metadata();
metadata.add(TikaMetadataKeys.RESOURCE_NAME_KEY, file.getName());
try (InputStream stream = file.getInputStream()) {
parser.parse(stream, new DefaultHandler(), metadata, parseContext);
} catch (Exception e) {
throw BizException.biz(e.getMessage());
}
return metadata.get(HttpHeaders.CONTENT_TYPE);
}
/**
* 根据使用HTTP/2获取网络资源
*
* @param url
* @return
* @throws IOException
*/
public static MultipartFile getMultipartFileByHttp2(String url) {
OkHttpClient client = new OkHttpClient.Builder()
.protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1))
.build();
Request request = new Request.Builder()
.url(url)
.build();
Response response;
try {
response = client.newCall(request).execute();
} catch (Exception e) {
throw BizException.biz(e.getMessage());
}
AssertUtils.isTrue(response.isSuccessful(), BizException.biz("Unexpected response code:%s" + response.code()));
ResponseBody body = response.body();
AssertUtils.notNull(body, BizException.biz("response body is null"));
try (InputStream inputStream = body.byteStream()) {
String fileName = interceptFileNameByUrl(url);
return new MockMultipartFile(fileName, fileName, MediaType.MULTIPART_FORM_DATA_VALUE, inputStream);
} catch (Exception e) {
throw BizException.biz(e.getMessage());
}
}
/**
* 根据url截取文件名
*
* @param url
* @return
*/
public static String interceptFileNameByUrl(String url) {
if (StringUtils.isBlank(url)) {
throw new IllegalArgumentException("url is null");
}
return url.substring(url.lastIndexOf("/") + 1);
}
/**
* 指定文件是否存在
*
* @param file
* @return
*/
public static boolean isFileExist(MultipartFile file) {
return file != null && !file.isEmpty();
}
}
用到maven依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-all-deps</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>1.24.1</version>
</dependency>