1
This commit is contained in:
@@ -66,7 +66,13 @@ image:
|
||||
项目已添加以下依赖:
|
||||
|
||||
1. **Thumbnailator** (0.4.20):图片处理库
|
||||
2. **webp-imageio** (0.1.0):WebP格式支持库
|
||||
|
||||
**注意**:WebP格式支持需要系统或JVM本身支持webp格式。如果系统不支持webp,转换功能会跳过webp图片并返回原URL,不会影响系统正常运行。
|
||||
|
||||
如需支持webp格式转换,可以:
|
||||
- 使用支持webp的JVM版本
|
||||
- 手动添加webp-imageio库到项目中
|
||||
- 使用其他webp解码库
|
||||
|
||||
## API接口
|
||||
|
||||
|
||||
18
pom.xml
18
pom.xml
@@ -119,12 +119,6 @@
|
||||
<artifactId>thumbnailator</artifactId>
|
||||
<version>0.4.20</version>
|
||||
</dependency>
|
||||
<!-- WebP图片格式支持 -->
|
||||
<dependency>
|
||||
<groupId>com.github.gotson</groupId>
|
||||
<artifactId>webp-imageio</artifactId>
|
||||
<version>0.1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -170,5 +164,17 @@
|
||||
<name>RocketMQ Repository</name>
|
||||
<url>https://repo1.maven.org/maven2/org/apache/rocketmq/</url>
|
||||
</repository>
|
||||
<!-- Maven 中央仓库 -->
|
||||
<repository>
|
||||
<id>central</id>
|
||||
<name>Maven Central Repository</name>
|
||||
<url>https://repo1.maven.org/maven2</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
</project>
|
||||
|
||||
@@ -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,36 +209,47 @@ 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 (webpSupported) {
|
||||
// 如果支持webp,尝试使用ImageIO读取
|
||||
try (ByteArrayInputStream bais = new ByteArrayInputStream(imageData)) {
|
||||
bufferedImage = 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 (bufferedImage == null) {
|
||||
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 (bufferedImage == null) {
|
||||
throw new IOException("无法读取webp图片格式,请确认已添加webp-imageio依赖");
|
||||
} 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
|
||||
if (bufferedImage.getType() == BufferedImage.TYPE_4BYTE_ABGR ||
|
||||
bufferedImage.getType() == BufferedImage.TYPE_INT_ARGB) {
|
||||
|
||||
Reference in New Issue
Block a user