package com.sinata.appointment.service;
|
|
import com.sinata.appointment.config.LocalFileUploadProperties;
|
import com.sinata.appointment.constants.BizErrorCode;
|
import com.sinata.appointment.exception.BizException;
|
import java.io.IOException;
|
import java.nio.file.Files;
|
import java.nio.file.Path;
|
import java.nio.file.StandardCopyOption;
|
import java.util.Set;
|
import java.util.UUID;
|
import org.springframework.stereotype.Service;
|
import org.springframework.util.StringUtils;
|
import org.springframework.web.multipart.MultipartFile;
|
|
@Service
|
public class LocalImageUploadService {
|
|
private static final long IMAGE_MAX_SIZE = 10L * 1024 * 1024;
|
private static final Set<String> IMAGE_EXTENSIONS = Set.of(".jpg", ".jpeg", ".png", ".webp", ".gif");
|
|
private final LocalFileUploadProperties localFileUploadProperties;
|
|
public LocalImageUploadService(LocalFileUploadProperties localFileUploadProperties) {
|
this.localFileUploadProperties = localFileUploadProperties;
|
}
|
|
public String uploadImage(MultipartFile file) {
|
if (file == null || file.isEmpty()) {
|
throw new BizException(BizErrorCode.AUTH_INVALID_CREDENTIALS, "图片文件不能为空");
|
}
|
if (file.getSize() > IMAGE_MAX_SIZE) {
|
throw new BizException(BizErrorCode.AUTH_INVALID_CREDENTIALS, "图片文件不能超过10MB");
|
}
|
String ext = normalizeImageExtension(file.getOriginalFilename(), file.getContentType());
|
String fileName = UUID.randomUUID().toString().replace("-", "") + ext;
|
Path uploadDir = Path.of(localFileUploadProperties.getFileUploadPath()).toAbsolutePath().normalize();
|
Path target = uploadDir.resolve(fileName).normalize();
|
if (!target.getParent().equals(uploadDir)) {
|
throw new BizException(BizErrorCode.AUTH_FORBIDDEN, "图片上传路径非法");
|
}
|
try {
|
Files.createDirectories(uploadDir);
|
Files.copy(file.getInputStream(), target, StandardCopyOption.REPLACE_EXISTING);
|
} catch (IOException ex) {
|
throw new BizException(BizErrorCode.AUTH_FORBIDDEN, "图片上传失败");
|
}
|
return buildPictureUrl(fileName);
|
}
|
|
private String buildPictureUrl(String fileName) {
|
String serverAddress = localFileUploadProperties.getPictureServerAddress();
|
if (!StringUtils.hasText(serverAddress)) {
|
return fileName;
|
}
|
return serverAddress.endsWith("/") ? serverAddress + fileName : serverAddress + "/" + fileName;
|
}
|
|
private String normalizeImageExtension(String originalFilename, String contentType) {
|
String ext = "";
|
if (StringUtils.hasText(originalFilename)) {
|
int idx = originalFilename.lastIndexOf('.');
|
if (idx >= 0) {
|
ext = originalFilename.substring(idx).toLowerCase();
|
}
|
}
|
if (!IMAGE_EXTENSIONS.contains(ext)) {
|
ext = switch (contentType == null ? "" : contentType.toLowerCase()) {
|
case "image/jpeg", "image/jpg" -> ".jpg";
|
case "image/png" -> ".png";
|
case "image/webp" -> ".webp";
|
case "image/gif" -> ".gif";
|
default -> "";
|
};
|
}
|
if (!IMAGE_EXTENSIONS.contains(ext)) {
|
throw new BizException(BizErrorCode.AUTH_INVALID_CREDENTIALS, "仅支持 jpg、jpeg、png、webp、gif 图片");
|
}
|
return ext;
|
}
|
}
|