7 小时以前 9bad721754fe8bbe2e5f459d0706e0fefac569f3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package cn.iocoder.yudao.module.qcreport.service.aiimport.document;
 
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
 
import java.util.List;
import java.util.Set;
 
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.qcreport.enums.ErrorCodeConstants.AI_IMPORT_FILE_EMPTY;
 
/**
 * 图片(照片 / 截图)抽取器。
 * <p>
 * 三种适配器里唯一「什么都不用做」的一个:字节原样交给多模态模型,不解码、不缩放、不转码。
 * 刻意不在这里用 {@code ImageIO} 读一遍——那不仅多一次内存拷贝,还会在遇到 webp 这类
 * JDK 原生不支持的格式时白白失败,而模型那边其实完全能认。
 * <p>
 * 排在第一位:它只认图片扩展名,与另外两个的匹配集不相交,放哪都不会引起歧义,
 * 但放在最前面能让「一张照片」这条最常见的路径以最短的路走到头。
 */
@Component
@Order(1)
public class ImageImportAdapter implements QcReportImportAdapter {
 
    private static final Set<String> EXTENSIONS = Set.of("png", "jpg", "jpeg", "bmp", "gif", "webp");
 
    @Override
    public boolean supports(String extension, String contentType) {
        return EXTENSIONS.contains(extension);
    }
 
    @Override
    public QcReportDocumentExtract extract(byte[] content, String originalFilename) {
        if (content == null || content.length == 0) {
            throw exception(AI_IMPORT_FILE_EMPTY, originalFilename, 1);
        }
        String mimeType = mimeTypeOf(extensionOf(originalFilename));
        return QcReportDocumentExtract.ofImages(
                List.of(new QcReportDocumentExtract.ImagePart(content, mimeType, "第 1 页")),
                1, "raw-image", List.of());
    }
 
    /**
     * PDF 适配器需要同一套映射来标注渲染出来的 PNG,所以公开出来复用。
     */
    static String mimeTypeOf(String extension) {
        return switch (extension) {
            case "jpg", "jpeg" -> "image/jpeg";
            case "gif" -> "image/gif";
            case "bmp" -> "image/bmp";
            case "webp" -> "image/webp";
            default -> "image/png";
        };
    }
 
    private static String extensionOf(String filename) {
        int dot = filename == null ? -1 : filename.lastIndexOf('.');
        return dot < 0 ? "" : filename.substring(dot + 1).toLowerCase();
    }
 
}