This commit is contained in:
2025-11-03 15:26:52 +08:00
parent 6b36f0ee52
commit 89b37907e7
3 changed files with 84 additions and 54 deletions

View File

@@ -10,12 +10,15 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import net.coobird.thumbnailator.Thumbnails;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -23,35 +26,37 @@ import java.time.LocalDateTime;
import java.util.*;
/**
* WebP图片IO支持
* 注册WebP图片格式的读写器
* WebP图片IO支持工具类
* 尝试使用可用的方式读取webp图片
*/
class WebPImageIO {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(WebPImageIO.class);
private static volatile boolean initialized = false;
private static volatile boolean webpSupported = false;
private static volatile boolean checked = false;
/**
* 初始化WebP支持
* webp-imageio库在类加载时会通过ServiceLoader自动注册到ImageIO
* 检查是否支持webp格式
*/
static synchronized void init() {
if (initialized) {
return;
static synchronized boolean isWebPSupported() {
if (checked) {
return webpSupported;
}
// 检查是否支持webp格式
try {
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("webp");
if (readers.hasNext()) {
log.debug("WebP图片格式支持已启用");
webpSupported = readers.hasNext();
if (webpSupported) {
log.info("WebP图片格式支持已启用");
} else {
log.warn("未检测到WebP图片格式支持webp转换可能失败。请确认webp-imageio依赖已正确加载");
log.warn("未检测到WebP图片格式支持webp图片转换将被跳过");
}
} catch (Exception e) {
log.warn("检查WebP支持时出错: {}", e.getMessage());
webpSupported = false;
}
initialized = true;
checked = true;
return webpSupported;
}
}
@@ -102,8 +107,8 @@ public class ImageConvertService {
String convertedUrl = convertImageUrl(imageUrl);
convertedUrls.add(convertedUrl);
} catch (Exception e) {
log.warn("图片转换失败使用原URL: {}, 错误: {}", imageUrl, e.getMessage());
// 转换失败使用原URL
// 转换失败使用原URL,不中断流程
log.warn("图片转换失败使用原URL: {}. 错误: {}", imageUrl, e.getMessage());
convertedUrls.add(imageUrl);
}
}
@@ -116,8 +121,9 @@ public class ImageConvertService {
*
* @param originalUrl 原始图片URL
* @return 转换后的图片URL如果不需要转换则返回原URL
* @throws Exception 转换过程中的异常调用方会捕获并返回原URL
*/
private String convertImageUrl(String originalUrl) {
private String convertImageUrl(String originalUrl) throws Exception {
if (StrUtil.isBlank(originalUrl)) {
return originalUrl;
}
@@ -127,6 +133,12 @@ public class ImageConvertService {
return originalUrl;
}
// 检查系统是否支持webp转换
if (!WebPImageIO.isWebPSupported()) {
log.debug("系统不支持webp格式跳过转换: {}", originalUrl);
throw new IOException("系统不支持webp格式转换");
}
// 检查是否已转换
Optional<ImageConversion> existing = imageConversionRepository.findByOriginalUrl(originalUrl);
if (existing.isPresent()) {
@@ -136,14 +148,9 @@ public class ImageConvertService {
}
// 执行转换
try {
String convertedUrl = performConversion(originalUrl);
log.info("图片转换成功: {} -> {}", originalUrl, convertedUrl);
return convertedUrl;
} catch (Exception e) {
log.error("图片转换失败: {}, 错误: {}", originalUrl, e.getMessage(), e);
throw e;
}
String convertedUrl = performConversion(originalUrl);
log.info("图片转换成功: {} -> {}", originalUrl, convertedUrl);
return convertedUrl;
}
/**
@@ -202,34 +209,45 @@ public class ImageConvertService {
// 转换图片格式
BufferedImage bufferedImage = null;
try {
// 初始化WebP支持
WebPImageIO.init();
// 检查是否支持webp格式
boolean webpSupported = WebPImageIO.isWebPSupported();
// 尝试使用ImageIO读取
BufferedImage tempImage = null;
try (ByteArrayInputStream bais = new ByteArrayInputStream(imageData)) {
tempImage = ImageIO.read(bais);
}
if (tempImage != null) {
bufferedImage = tempImage;
} else {
// 如果ImageIO无法读取尝试使用WebP特定的读取器
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("webp");
if (readers.hasNext()) {
ImageReader reader = readers.next();
try (ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
ImageInputStream iis = ImageIO.createImageInputStream(bais)) {
reader.setInput(iis);
bufferedImage = reader.read(0);
} finally {
reader.dispose();
}
if (webpSupported) {
// 如果支持webp尝试使用ImageIO读取
try (ByteArrayInputStream bais = new ByteArrayInputStream(imageData)) {
bufferedImage = ImageIO.read(bais);
}
// 如果ImageIO无法读取尝试使用WebP特定的读取器
if (bufferedImage == null) {
throw new IOException("无法读取webp图片格式请确认已添加webp-imageio依赖");
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("webp");
if (readers.hasNext()) {
ImageReader reader = readers.next();
try (ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
ImageInputStream iis = ImageIO.createImageInputStream(bais)) {
reader.setInput(iis);
bufferedImage = reader.read(0);
} finally {
reader.dispose();
}
}
}
} else {
// 如果不支持webp尝试使用Thumbnailator转换
// 注意Thumbnailator内部也使用ImageIO所以通常也无法处理webp
try (ByteArrayInputStream bais = new ByteArrayInputStream(imageData)) {
bufferedImage = Thumbnails.of(bais)
.scale(1.0)
.asBufferedImage();
} catch (Exception e) {
log.debug("Thumbnailator无法读取webp图片: {}", e.getMessage());
// 如果无法转换抛出异常后续会返回原URL
throw new IOException("当前系统不支持webp格式转换。图片将保持原格式返回。", e);
}
}
if (bufferedImage == null) {
throw new IOException("无法读取webp图片格式。当前系统不支持webp格式转换。");
}
// 如果是RGBA格式转换为RGB