优化
This commit is contained in:
@@ -8,6 +8,8 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
@@ -15,6 +17,7 @@ import java.nio.file.Path;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HexFormat;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
@@ -36,7 +39,7 @@ public class ProductImageStorage {
|
||||
if (file.getSize() > MAX_SIZE) throw bad("产品图片不能超过5MB");
|
||||
String type = file.getContentType() == null ? "" : file.getContentType().toLowerCase(Locale.ROOT);
|
||||
if (!TYPES.contains(type)) throw bad("产品图片仅支持JPG、PNG");
|
||||
verifyImage(file);
|
||||
verifyImage(file, type);
|
||||
String extension = "image/png".equals(type) ? ".png" : ".jpg";
|
||||
String objectKey = "product-images/" + tenantId + "/" + UUID.randomUUID() + extension;
|
||||
Path target = root.resolve(objectKey).normalize();
|
||||
@@ -72,9 +75,23 @@ public class ProductImageStorage {
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyImage(MultipartFile file) {
|
||||
try (InputStream input = file.getInputStream()) {
|
||||
if (ImageIO.read(input) == null) throw bad("上传内容不是有效图片");
|
||||
private void verifyImage(MultipartFile file, String declaredType) {
|
||||
try (InputStream input = file.getInputStream();
|
||||
ImageInputStream imageInput = ImageIO.createImageInputStream(input)) {
|
||||
if (imageInput == null) throw bad("上传内容不是有效图片");
|
||||
Iterator<ImageReader> readers = ImageIO.getImageReaders(imageInput);
|
||||
if (!readers.hasNext()) throw bad("上传内容不是有效图片");
|
||||
ImageReader reader = readers.next();
|
||||
try {
|
||||
String format = reader.getFormatName().toLowerCase(Locale.ROOT);
|
||||
boolean matches = "image/png".equals(declaredType) ? "png".equals(format)
|
||||
: "jpeg".equals(format) || "jpg".equals(format);
|
||||
if (!matches) throw bad("图片内容与文件类型不一致");
|
||||
reader.setInput(imageInput, true, true);
|
||||
reader.read(0);
|
||||
} finally {
|
||||
reader.dispose();
|
||||
}
|
||||
} catch (IOException exception) {
|
||||
throw bad("上传内容不是有效图片");
|
||||
}
|
||||
@@ -96,7 +113,11 @@ public class ProductImageStorage {
|
||||
private static String safeName(MultipartFile file) {
|
||||
String name = file.getOriginalFilename();
|
||||
if (name == null || name.isBlank()) return "product-image";
|
||||
return Path.of(name).getFileName().toString();
|
||||
String normalized = name.replace('\\', '/');
|
||||
String leaf = normalized.substring(normalized.lastIndexOf('/') + 1)
|
||||
.replaceAll("[\\p{Cntrl}]", "").trim();
|
||||
if (leaf.isEmpty()) return "product-image";
|
||||
return leaf.length() <= 255 ? leaf : leaf.substring(leaf.length() - 255);
|
||||
}
|
||||
|
||||
private static BizException bad(String message) {
|
||||
|
||||
Reference in New Issue
Block a user