cmvr-wms/ruoyi-system/src/main/java/com/ruoyi/warehouse/util/WarehouseFileUtils.java

145 lines
4.4 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.ruoyi.warehouse.util;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
public final class WarehouseFileUtils
{
private static final long MAX_IMAGE_PIXELS = 40_000_000L;
private WarehouseFileUtils()
{
}
public static String validateUpload(MultipartFile file, long maxFileSize, Set<String> allowedExtensions)
{
if (file == null || file.isEmpty())
{
throw new ServiceException("请选择要上传的文件");
}
if (file.getSize() > maxFileSize)
{
throw new ServiceException("文件不能超过" + (maxFileSize / 1024 / 1024) + "MB");
}
String extension = StringUtils.defaultString(FilenameUtils.getExtension(file.getOriginalFilename()))
.toLowerCase(Locale.ROOT);
if (!allowedExtensions.contains(extension))
{
throw new ServiceException("不支持的文件类型");
}
try
{
byte[] header;
try (InputStream input = file.getInputStream())
{
header = input.readNBytes(12);
}
if ("xls".equals(extension) && !startsWith(header, 0xD0, 0xCF, 0x11, 0xE0))
{
throw new ServiceException("文件内容不是有效的Excel文件");
}
if ("xlsx".equals(extension) && !startsWith(header, 0x50, 0x4B))
{
throw new ServiceException("文件内容不是有效的Excel文件");
}
if (isImage(extension))
{
validateImage(file, extension, header);
}
return extension;
}
catch (ServiceException e)
{
throw e;
}
catch (Exception e)
{
throw new ServiceException("无法读取上传文件,请确认文件未损坏");
}
}
private static void validateImage(MultipartFile file, String extension, byte[] header) throws Exception
{
if ("webp".equals(extension))
{
if (!matchesAscii(header, 0, "RIFF") || !matchesAscii(header, 8, "WEBP"))
{
throw new ServiceException("文件内容不是有效的WebP图片");
}
return;
}
try (ImageInputStream input = ImageIO.createImageInputStream(file.getInputStream()))
{
if (input == null)
{
throw new ServiceException("文件内容不是有效图片");
}
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
if (!readers.hasNext())
{
throw new ServiceException("文件内容不是有效图片");
}
ImageReader reader = readers.next();
try
{
reader.setInput(input, true, true);
long pixels = (long) reader.getWidth(0) * reader.getHeight(0);
if (pixels <= 0 || pixels > MAX_IMAGE_PIXELS)
{
throw new ServiceException("图片尺寸过大,最大支持4000万像素");
}
}
finally
{
reader.dispose();
}
}
}
private static boolean isImage(String extension)
{
return Set.of("jpg", "jpeg", "png", "bmp", "webp").contains(extension);
}
private static boolean startsWith(byte[] source, int... prefix)
{
if (source.length < prefix.length)
{
return false;
}
for (int i = 0; i < prefix.length; i++)
{
if ((source[i] & 0xFF) != prefix[i])
{
return false;
}
}
return true;
}
private static boolean matchesAscii(byte[] source, int offset, String expected)
{
if (source.length < offset + expected.length())
{
return false;
}
for (int i = 0; i < expected.length(); i++)
{
if (source[offset + i] != (byte) expected.charAt(i))
{
return false;
}
}
return true;
}
}