Thumbnailator 是 Google 開源的 Java 圖片處理庫,API 設計極簡,兩三行代碼即可完成縮放、裁剪、水印、旋轉等操作,處理效果優於原生 Java API,且持續維護更新。
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
// 縮放至 400x500 範圍內,保持原圖比例 Thumbnails.of(fromPic).size(400, 500).toFile(toPic);
// 縮小至 20% Thumbnails.of(fromPic).scale(0.2f).toFile(toPic); // 放大至 200% Thumbnails.of(fromPic).scale(2f).toFile(toPic);
// 品質參數 0.25f(1.0 為最高品質) Thumbnails.of(fromPic).scale(1f).outputQuality(0.25f).toFile(toPic);
/**
* 上傳圖片並生成縮略圖
* @param imageFile 上傳文件
* @param request 請求對象
* @param uploadPath 上傳目錄
* @return 處理結果
*/
public static BaseResult uploadFileAndCreateThumbnail(MultipartFile imageFile,
HttpServletRequest request, String uploadPath) {
// 參數校驗
if (imageFile == null) {
return new BaseResult(false, "imageFile不能為空");
}
if (imageFile.getSize() >= 10 * 1024 * 1024) {
return new BaseResult(false, "文件不能大於10M");
}
// 生成唯一文件名
String uuid = UUID.randomUUID().toString();
String dateDir = CommonDateUtils.date2string(new Date(), CommonDateUtils.YYYY_MM_DD);
String ext = FilenameUtils.getExtension(imageFile.getOriginalFilename());
String pathName = dateDir + File.separator + uuid + "." + ext;
// 構建服務器絕對路徑
String realPath = request.getServletContext().getRealPath(uploadPath);
String filePathName = realPath + File.separator + pathName;
// 確保目錄存在
File file = new File(filePathName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
// 寫入原圖
try (InputStream inputStream = imageFile.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream(file)) {
byte[] buffer = new byte[2048];
IOUtils.copyLarge(inputStream, fileOutputStream, buffer);
} catch (IOException e) {
return new BaseResult(false, "操作失敗", e.getMessage());
}
// 生成縮略圖邏輯
String thumbnailPathName = dateDir + File.separator + uuid + "small." + ext;
if (thumbnailPathName.contains(".png")) {
thumbnailPathName = thumbnailPathName.replace(".png", ".jpg");
}
long size = imageFile.getSize();
double scale = 1.0;
if (size >= 200 * 1024) {
scale = (200 * 1024f) / size;
}
String thumbnailFilePathName = realPath + File.separator + thumbnailPathName;
try {
if (size < 200 * 1024) {
// 小文件僅轉格式
Thumbnails.of(filePathName).scale(1f).outputFormat("jpg").toFile(thumbnailFilePathName);
} else {
// 大文件壓縮品質
Thumbnails.of(filePathName)
.scale(1f)
.outputQuality(scale)
.outputFormat("jpg")
.toFile(thumbnailFilePathName);
}
} catch (Exception e) {
return new BaseResult(false, "操作失敗", e.getMessage());
}
// 返回結果
Map<String, Object> result = new HashMap<>();
result.put("originalUrl", pathName);
result.put("thumbnailUrl", thumbnailPathName);
return new BaseResult(true, "操作成功", result);
}
public class PropertiesUtil {
private static final PropertiesUtil INSTANCE = new PropertiesUtil();
private final ConcurrentHashMap<String, Properties> cache = new ConcurrentHashMap<>();
private final Logger logger = LoggerFactory.getLogger(PropertiesUtil.class);
private PropertiesUtil() {}
public static PropertiesUtil getInstance() {
return INSTANCE;
}
public String getSysPro(String key) {
return getSysPro(key, null);
}
public String getSysPro(String key, String defaultValue) {
String profile = System.getProperty("spring.profiles.active");
String fileName = "spring/imageserver-" + profile + ".properties";
return getValue(fileName, key, defaultValue);
}
private String getValue(String fileName, String key, String defaultValue) {
Properties props = cache.get(fileName);
if (props == null) {
try (InputStream is = PropertiesUtil.class.getClassLoader().getResourceAsStream(fileName)) {
if (is != null) {
props = new Properties();
props.load(new InputStreamReader(is, "UTF-8"));
cache.put(fileName, props);
}
} catch (IOException e) {
logger.error("載入配置失敗: {}", fileName, e);
}
}
return props != null ? props.getProperty(key, defaultValue) : defaultValue;
}
}
// 獲取上傳路徑配置
String uploadPath = PropertiesUtil.getInstance().getSysPro("uploadPath");