You've already forked FrameTour-BE
feat(image): 实现源图片超分辨率增强流水线
- 引入Pipeline模式重构图片处理流程 - 新增SourcePhotoUpdateStage用于上传并更新源图片URL - 扩展PhotoProcessContext支持超分场景配置 - 增加SOURCE_PHOTO_SUPER_RESOLUTION枚举值 - 修改各Stage判断逻辑适配新的图片类型系统 - 调整SourceService接口支持File类型参数 - 优化超分处理日志记录和异常处理机制
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
package com.ycwl.basic.image.pipeline.annotation;
|
||||
|
||||
import com.ycwl.basic.image.pipeline.enums.StageOptionalMode;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Stage配置注解
|
||||
* 用于声明Stage的元数据和可选性控制信息
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface StageConfig {
|
||||
|
||||
/**
|
||||
* Stage的唯一标识
|
||||
* 用于外部配置引用该Stage
|
||||
* 例如: "watermark", "download", "upload"
|
||||
*/
|
||||
String stageId();
|
||||
|
||||
/**
|
||||
* 可选性模式
|
||||
* 默认为UNSUPPORT(不支持外部控制)
|
||||
*/
|
||||
StageOptionalMode optionalMode() default StageOptionalMode.UNSUPPORT;
|
||||
|
||||
/**
|
||||
* Stage描述信息
|
||||
* 用于文档和日志说明
|
||||
*/
|
||||
String description() default "";
|
||||
|
||||
/**
|
||||
* 默认是否启用
|
||||
* 仅当optionalMode=SUPPORT时有效
|
||||
* 当外部配置未明确指定时,使用此默认值
|
||||
*/
|
||||
boolean defaultEnabled() default true;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.ycwl.basic.image.pipeline.core;
|
||||
import com.ycwl.basic.image.watermark.entity.WatermarkInfo;
|
||||
import com.ycwl.basic.image.watermark.enums.ImageWatermarkOperatorEnum;
|
||||
import com.ycwl.basic.image.pipeline.enums.ImageSource;
|
||||
import com.ycwl.basic.image.pipeline.enums.ImageType;
|
||||
import com.ycwl.basic.image.pipeline.enums.PipelineScene;
|
||||
import com.ycwl.basic.integration.common.manager.ScenicConfigManager;
|
||||
import com.ycwl.basic.model.Crop;
|
||||
@@ -15,6 +16,8 @@ import lombok.Setter;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* 图片处理管线上下文
|
||||
@@ -24,10 +27,43 @@ import java.util.Map;
|
||||
@Setter
|
||||
public class PhotoProcessContext {
|
||||
|
||||
private final PrinterOrderItem orderItem;
|
||||
private final TempFileManager tempFileManager;
|
||||
// ==================== 核心字段(构造时必填)====================
|
||||
|
||||
/**
|
||||
* 处理过程唯一标识
|
||||
* 用于 TempFileManager 创建隔离的临时文件目录
|
||||
*/
|
||||
private final String processId;
|
||||
|
||||
/**
|
||||
* 原图 URL
|
||||
*/
|
||||
private final String originalUrl;
|
||||
|
||||
/**
|
||||
* 景区 ID
|
||||
*/
|
||||
private final Long scenicId;
|
||||
|
||||
/**
|
||||
* 临时文件管理器
|
||||
*/
|
||||
private final TempFileManager tempFileManager;
|
||||
|
||||
// ==================== 图片元信息 ====================
|
||||
|
||||
/**
|
||||
* 图片类型
|
||||
*/
|
||||
private ImageType imageType = ImageType.NORMAL_PHOTO;
|
||||
|
||||
/**
|
||||
* 裁剪/旋转信息
|
||||
*/
|
||||
private Crop crop;
|
||||
|
||||
// ==================== 管线配置 ====================
|
||||
|
||||
/**
|
||||
* 景区配置管理器,用于获取景区相关配置
|
||||
*/
|
||||
@@ -50,6 +86,8 @@ public class PhotoProcessContext {
|
||||
*/
|
||||
private Map<String, Boolean> stageEnabledMap = new HashMap<>();
|
||||
|
||||
// ==================== 处理过程状态 ====================
|
||||
|
||||
private File originalFile;
|
||||
private File processedFile;
|
||||
private boolean isLandscape = true;
|
||||
@@ -62,14 +100,78 @@ public class PhotoProcessContext {
|
||||
private String dateFormat;
|
||||
private File qrcodeFile;
|
||||
private Integer offsetLeft;
|
||||
private Crop crop;
|
||||
|
||||
public PhotoProcessContext(PrinterOrderItem orderItem, Long scenicId) {
|
||||
this.orderItem = orderItem;
|
||||
this.scenicId = scenicId;
|
||||
this.tempFileManager = new TempFileManager(orderItem.getId().toString());
|
||||
// ==================== 回调 ====================
|
||||
|
||||
/**
|
||||
* 结果 URL 回调
|
||||
* 用于在 setResultUrl 时通知外部更新相关数据
|
||||
*/
|
||||
private Consumer<String> resultUrlCallback;
|
||||
|
||||
// ==================== 构造函数(私有)====================
|
||||
|
||||
private PhotoProcessContext(Builder builder) {
|
||||
this.processId = builder.processId;
|
||||
this.originalUrl = builder.originalUrl;
|
||||
this.scenicId = builder.scenicId;
|
||||
this.tempFileManager = new TempFileManager(processId);
|
||||
|
||||
this.imageType = builder.imageType;
|
||||
this.crop = builder.crop;
|
||||
this.scene = builder.scene;
|
||||
this.source = builder.source;
|
||||
this.resultUrlCallback = builder.resultUrlCallback;
|
||||
}
|
||||
|
||||
// ==================== 静态工厂方法 ====================
|
||||
|
||||
/**
|
||||
* 从 PrinterOrderItem 创建 Context(打印场景兼容方法)
|
||||
*
|
||||
* @param orderItem 打印订单项
|
||||
* @param scenicId 景区ID
|
||||
* @return PhotoProcessContext
|
||||
*/
|
||||
public static PhotoProcessContext fromPrinterOrderItem(PrinterOrderItem orderItem, Long scenicId) {
|
||||
return PhotoProcessContext.builder()
|
||||
.processId(orderItem.getId().toString())
|
||||
.originalUrl(orderItem.getCropUrl())
|
||||
.scenicId(scenicId)
|
||||
.imageType(ImageType.fromSourceId(orderItem.getSourceId()))
|
||||
.crop(orderItem.getCrop())
|
||||
.resultUrlCallback(url -> orderItem.setCropUrl(url))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 为超分辨率场景创建 Context
|
||||
*
|
||||
* @param itemId 项目ID(用于临时文件隔离)
|
||||
* @param url 原图URL
|
||||
* @param scenicId 景区ID
|
||||
* @return PhotoProcessContext
|
||||
*/
|
||||
public static PhotoProcessContext forSuperResolution(Long itemId, String url, Long scenicId) {
|
||||
return PhotoProcessContext.builder()
|
||||
.processId(itemId.toString())
|
||||
.originalUrl(url)
|
||||
.scenicId(scenicId)
|
||||
.imageType(ImageType.NORMAL_PHOTO)
|
||||
.source(ImageSource.IPC)
|
||||
.scene(PipelineScene.SOURCE_PHOTO_SUPER_RESOLUTION)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Builder
|
||||
*/
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
// ==================== 业务方法 ====================
|
||||
|
||||
/**
|
||||
* 从景区配置和请求参数中加载Stage开关配置
|
||||
*
|
||||
@@ -94,33 +196,14 @@ public class PhotoProcessContext {
|
||||
return stageEnabledMap.getOrDefault(stageId, defaultEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为拼图类型
|
||||
*/
|
||||
public boolean isPuzzle() {
|
||||
return orderItem.getSourceId() != null && orderItem.getSourceId() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为普通照片
|
||||
*/
|
||||
public boolean isNormalPhoto() {
|
||||
return orderItem.getSourceId() != null && orderItem.getSourceId() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取原图URL
|
||||
*/
|
||||
public String getOriginalUrl() {
|
||||
return orderItem.getCropUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置最终处理结果URL
|
||||
*/
|
||||
public void setResultUrl(String url) {
|
||||
this.resultUrl = url;
|
||||
this.orderItem.setCropUrl(url);
|
||||
if (resultUrlCallback != null) {
|
||||
resultUrlCallback.accept(url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,4 +228,72 @@ public class PhotoProcessContext {
|
||||
public void cleanup() {
|
||||
tempFileManager.cleanup();
|
||||
}
|
||||
|
||||
// ==================== Builder ====================
|
||||
|
||||
public static class Builder {
|
||||
private String processId;
|
||||
private String originalUrl;
|
||||
private Long scenicId;
|
||||
private ImageType imageType = ImageType.NORMAL_PHOTO;
|
||||
private Crop crop;
|
||||
private PipelineScene scene;
|
||||
private ImageSource source;
|
||||
private Consumer<String> resultUrlCallback;
|
||||
|
||||
public Builder processId(String processId) {
|
||||
this.processId = processId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder originalUrl(String originalUrl) {
|
||||
this.originalUrl = originalUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder scenicId(Long scenicId) {
|
||||
this.scenicId = scenicId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder imageType(ImageType imageType) {
|
||||
this.imageType = imageType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder crop(Crop crop) {
|
||||
this.crop = crop;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder scene(PipelineScene scene) {
|
||||
this.scene = scene;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder source(ImageSource source) {
|
||||
this.source = source;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder resultUrlCallback(Consumer<String> callback) {
|
||||
this.resultUrlCallback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PhotoProcessContext build() {
|
||||
// 参数校验
|
||||
if (originalUrl == null || originalUrl.isBlank()) {
|
||||
throw new IllegalArgumentException("originalUrl is required");
|
||||
}
|
||||
if (scenicId == null) {
|
||||
throw new IllegalArgumentException("scenicId is required");
|
||||
}
|
||||
// processId 可以自动生成
|
||||
if (processId == null || processId.isBlank()) {
|
||||
processId = UUID.randomUUID().toString();
|
||||
}
|
||||
return new PhotoProcessContext(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.ycwl.basic.image.pipeline.enums;
|
||||
|
||||
/**
|
||||
* 图片类型枚举
|
||||
* 用于区分管线处理的图片类型,替代通过 sourceId 判断的逻辑
|
||||
*/
|
||||
public enum ImageType {
|
||||
|
||||
/**
|
||||
* 普通照片
|
||||
* 对应原 sourceId > 0 的情况(IPC设备拍摄)
|
||||
*/
|
||||
NORMAL_PHOTO("normal", "普通照片"),
|
||||
|
||||
/**
|
||||
* 拼图
|
||||
* 对应原 sourceId == 0 的情况
|
||||
*/
|
||||
PUZZLE("puzzle", "拼图"),
|
||||
|
||||
/**
|
||||
* 手机上传
|
||||
* 对应原 sourceId == null 的情况
|
||||
*/
|
||||
MOBILE_UPLOAD("mobile", "手机上传");
|
||||
|
||||
private final String code;
|
||||
private final String description;
|
||||
|
||||
ImageType(String code, String description) {
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 sourceId 推断图片类型
|
||||
* 用于兼容现有数据结构
|
||||
*
|
||||
* @param sourceId 源ID(null=手机上传, 0=拼图, >0=普通照片)
|
||||
* @return 对应的图片类型
|
||||
*/
|
||||
public static ImageType fromSourceId(Long sourceId) {
|
||||
if (sourceId == null) {
|
||||
return MOBILE_UPLOAD;
|
||||
} else if (sourceId == 0) {
|
||||
return PUZZLE;
|
||||
} else {
|
||||
return NORMAL_PHOTO;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,13 @@ public enum PipelineScene {
|
||||
* 图片增强场景
|
||||
* 包括图片美化、滤镜处理等
|
||||
*/
|
||||
IMAGE_ENHANCE("image_enhance", "图片增强");
|
||||
IMAGE_ENHANCE("image_enhance", "图片增强"),
|
||||
|
||||
/**
|
||||
* 源图片超分辨率增强场景
|
||||
* IPC设备拍摄的源图片进行质量提升
|
||||
*/
|
||||
SOURCE_PHOTO_SUPER_RESOLUTION("source_photo_sr", "源图片超分辨率增强");
|
||||
|
||||
private final String code;
|
||||
private final String description;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.ycwl.basic.image.pipeline.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* Stage可选性模式枚举
|
||||
* 定义Stage是否支持外部配置控制
|
||||
*/
|
||||
@Getter
|
||||
public enum StageOptionalMode {
|
||||
|
||||
/**
|
||||
* 不支持外部控制
|
||||
* Stage的执行完全由代码中的业务逻辑决定
|
||||
*/
|
||||
UNSUPPORT("不支持外部控制"),
|
||||
|
||||
/**
|
||||
* 支持外部控制
|
||||
* Stage可以通过景区配置或请求参数进行开启/关闭
|
||||
*/
|
||||
SUPPORT("支持外部控制"),
|
||||
|
||||
/**
|
||||
* 强制开启
|
||||
* Stage必须执行,不允许外部配置关闭
|
||||
*/
|
||||
FORCE_ON("强制开启");
|
||||
|
||||
private final String description;
|
||||
|
||||
StageOptionalMode(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.ycwl.basic.image.pipeline.annotation.StageConfig;
|
||||
import com.ycwl.basic.image.pipeline.core.AbstractPipelineStage;
|
||||
import com.ycwl.basic.image.pipeline.core.PhotoProcessContext;
|
||||
import com.ycwl.basic.image.pipeline.core.StageResult;
|
||||
import com.ycwl.basic.image.pipeline.enums.ImageType;
|
||||
import com.ycwl.basic.image.pipeline.enums.StageOptionalMode;
|
||||
import com.ycwl.basic.utils.ImageUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -31,7 +32,7 @@ public class ConditionalRotateStage extends AbstractPipelineStage<PhotoProcessCo
|
||||
|
||||
@Override
|
||||
protected boolean shouldExecuteByBusinessLogic(PhotoProcessContext context) {
|
||||
return context.isNormalPhoto() && !context.isLandscape();
|
||||
return context.getImageType() == ImageType.NORMAL_PHOTO && !context.isLandscape();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.ycwl.basic.image.pipeline.annotation.StageConfig;
|
||||
import com.ycwl.basic.image.pipeline.core.AbstractPipelineStage;
|
||||
import com.ycwl.basic.image.pipeline.core.PhotoProcessContext;
|
||||
import com.ycwl.basic.image.pipeline.core.StageResult;
|
||||
import com.ycwl.basic.image.pipeline.enums.ImageType;
|
||||
import com.ycwl.basic.image.pipeline.enums.StageOptionalMode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -38,7 +39,7 @@ public class DownloadStage extends AbstractPipelineStage<PhotoProcessContext> {
|
||||
|
||||
try {
|
||||
String fileExtension = determineFileExtension(context);
|
||||
String filePrefix = context.isPuzzle() ? "puzzle" : "print";
|
||||
String filePrefix = context.getImageType() == ImageType.PUZZLE ? "puzzle" : "print";
|
||||
|
||||
File downloadFile = context.getTempFileManager()
|
||||
.createTempFile(filePrefix, fileExtension);
|
||||
@@ -63,7 +64,7 @@ public class DownloadStage extends AbstractPipelineStage<PhotoProcessContext> {
|
||||
}
|
||||
|
||||
private String determineFileExtension(PhotoProcessContext context) {
|
||||
if (context.isPuzzle()) {
|
||||
if (context.getImageType() == ImageType.PUZZLE) {
|
||||
return ".png";
|
||||
}
|
||||
String url = context.getOriginalUrl();
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.ycwl.basic.image.pipeline.annotation.StageConfig;
|
||||
import com.ycwl.basic.image.pipeline.core.AbstractPipelineStage;
|
||||
import com.ycwl.basic.image.pipeline.core.PhotoProcessContext;
|
||||
import com.ycwl.basic.image.pipeline.core.StageResult;
|
||||
import com.ycwl.basic.image.pipeline.enums.ImageType;
|
||||
import com.ycwl.basic.image.pipeline.enums.StageOptionalMode;
|
||||
import com.ycwl.basic.utils.ImageUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -30,7 +31,7 @@ public class ImageOrientationStage extends AbstractPipelineStage<PhotoProcessCon
|
||||
|
||||
@Override
|
||||
protected boolean shouldExecuteByBusinessLogic(PhotoProcessContext context) {
|
||||
return context.isNormalPhoto();
|
||||
return context.getImageType() == ImageType.NORMAL_PHOTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.ycwl.basic.image.pipeline.annotation.StageConfig;
|
||||
import com.ycwl.basic.image.pipeline.core.AbstractPipelineStage;
|
||||
import com.ycwl.basic.image.pipeline.core.PhotoProcessContext;
|
||||
import com.ycwl.basic.image.pipeline.core.StageResult;
|
||||
import com.ycwl.basic.image.pipeline.enums.ImageType;
|
||||
import com.ycwl.basic.image.pipeline.enums.StageOptionalMode;
|
||||
import com.ycwl.basic.utils.ImageUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -45,7 +46,7 @@ public class ImageQualityCheckStage extends AbstractPipelineStage<PhotoProcessCo
|
||||
@Override
|
||||
protected boolean shouldExecuteByBusinessLogic(PhotoProcessContext context) {
|
||||
// 仅对普通照片执行质量检测
|
||||
return context.isNormalPhoto();
|
||||
return context.getImageType() == ImageType.NORMAL_PHOTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.ycwl.basic.image.pipeline.annotation.StageConfig;
|
||||
import com.ycwl.basic.image.pipeline.core.AbstractPipelineStage;
|
||||
import com.ycwl.basic.image.pipeline.core.PhotoProcessContext;
|
||||
import com.ycwl.basic.image.pipeline.core.StageResult;
|
||||
import com.ycwl.basic.image.pipeline.enums.ImageType;
|
||||
import com.ycwl.basic.image.pipeline.enums.StageOptionalMode;
|
||||
import com.ycwl.basic.utils.ImageUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -34,7 +35,7 @@ public class PuzzleBorderStage extends AbstractPipelineStage<PhotoProcessContext
|
||||
|
||||
@Override
|
||||
protected boolean shouldExecuteByBusinessLogic(PhotoProcessContext context) {
|
||||
return context.isPuzzle();
|
||||
return context.getImageType() == ImageType.PUZZLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.ycwl.basic.image.pipeline.annotation.StageConfig;
|
||||
import com.ycwl.basic.image.pipeline.core.AbstractPipelineStage;
|
||||
import com.ycwl.basic.image.pipeline.core.PhotoProcessContext;
|
||||
import com.ycwl.basic.image.pipeline.core.StageResult;
|
||||
import com.ycwl.basic.image.pipeline.enums.ImageType;
|
||||
import com.ycwl.basic.image.pipeline.enums.StageOptionalMode;
|
||||
import com.ycwl.basic.utils.ImageUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -29,7 +30,7 @@ public class RestoreOrientationStage extends AbstractPipelineStage<PhotoProcessC
|
||||
|
||||
@Override
|
||||
protected boolean shouldExecuteByBusinessLogic(PhotoProcessContext context) {
|
||||
return context.isNormalPhoto() && context.isNeedRotation();
|
||||
return context.getImageType() == ImageType.NORMAL_PHOTO && context.isNeedRotation();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.ycwl.basic.image.pipeline.stages;
|
||||
|
||||
import com.ycwl.basic.image.pipeline.annotation.StageConfig;
|
||||
import com.ycwl.basic.image.pipeline.core.AbstractPipelineStage;
|
||||
import com.ycwl.basic.image.pipeline.core.PhotoProcessContext;
|
||||
import com.ycwl.basic.image.pipeline.core.StageResult;
|
||||
import com.ycwl.basic.image.pipeline.enums.StageOptionalMode;
|
||||
import com.ycwl.basic.service.pc.SourceService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* 源图片上传和更新Stage
|
||||
* 专门用于将增强后的图片上传并更新数据库中的URL
|
||||
*
|
||||
* 与UploadStage的区别:
|
||||
* - UploadStage: 通用上传,仅上传到存储并设置Context.resultUrl
|
||||
* - SourcePhotoUpdateStage: 专门用于源图片,上传+更新数据库source表的URL字段
|
||||
*/
|
||||
@Slf4j
|
||||
@StageConfig(
|
||||
stageId = "source_photo_update",
|
||||
optionalMode = StageOptionalMode.FORCE_ON,
|
||||
description = "源图片上传和数据库更新",
|
||||
defaultEnabled = true
|
||||
)
|
||||
public class SourcePhotoUpdateStage extends AbstractPipelineStage<PhotoProcessContext> {
|
||||
|
||||
private final SourceService sourceService;
|
||||
private final Long sourceId;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*
|
||||
* @param sourceService 源图片服务
|
||||
* @param sourceId 源图片ID
|
||||
*/
|
||||
public SourcePhotoUpdateStage(SourceService sourceService, Long sourceId) {
|
||||
this.sourceService = sourceService;
|
||||
this.sourceId = sourceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "SourcePhotoUpdateStage";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StageResult doExecute(PhotoProcessContext context) {
|
||||
File fileToUpload = context.getCurrentFile();
|
||||
if (fileToUpload == null || !fileToUpload.exists()) {
|
||||
return StageResult.failed("没有可上传的文件");
|
||||
}
|
||||
|
||||
if (sourceService == null) {
|
||||
return StageResult.failed("SourceService未注入");
|
||||
}
|
||||
|
||||
if (sourceId == null) {
|
||||
return StageResult.failed("SourceId为空");
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// 调用SourceService上传并更新URL
|
||||
String uploadedUrl = sourceService.uploadAndUpdateUrl(sourceId, fileToUpload);
|
||||
|
||||
// 设置结果URL到Context
|
||||
context.setResultUrl(uploadedUrl);
|
||||
|
||||
log.info("源图片上传并更新成功: sourceId={}, url={}", sourceId, uploadedUrl);
|
||||
|
||||
return StageResult.success("已上传并更新: " + uploadedUrl);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("源图片上传并更新失败: sourceId={}", sourceId, e);
|
||||
return StageResult.failed("上传并更新失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import com.ycwl.basic.image.pipeline.annotation.StageConfig;
|
||||
import com.ycwl.basic.image.pipeline.core.AbstractPipelineStage;
|
||||
import com.ycwl.basic.image.pipeline.core.PhotoProcessContext;
|
||||
import com.ycwl.basic.image.pipeline.core.StageResult;
|
||||
import com.ycwl.basic.image.pipeline.enums.ImageType;
|
||||
import com.ycwl.basic.image.pipeline.enums.StageOptionalMode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -37,7 +38,7 @@ public class WatermarkStage extends AbstractPipelineStage<PhotoProcessContext> {
|
||||
|
||||
@Override
|
||||
protected boolean shouldExecuteByBusinessLogic(PhotoProcessContext context) {
|
||||
return context.isNormalPhoto();
|
||||
return context.getImageType() == ImageType.NORMAL_PHOTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user