You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何避免硬编码图片文件扩展名?

优化硬编码文件扩展名的几种方案

方案一:用枚举类统一管理扩展名与FileType映射

把所有扩展名和对应的FileType封装到枚举中集中管理,既避免散落在代码各处的硬编码,还能统一处理扩展名的大小写、带点/不带点的格式问题,后续修改规则只需更新枚举即可。

import java.util.Set;
import java.util.stream.Collectors;

public enum FileTypeMapping {
    ZIP(Set.of("zip"), FileType.ZIP),
    IMAGE(Set.of("jpg", "jpeg", "png", "bmp", "svg", "webp", "jfif", "pjpeg", "pjp", "apng", "avif"), FileType.IMAGE);

    private final Set<String> extensions;
    private final FileType fileType;

    FileTypeMapping(Set<String> extensions, FileType fileType) {
        // 统一转小写并去掉点,兼容不同格式的扩展名输入
        this.extensions = extensions.stream()
                .map(ext -> ext.toLowerCase().replace(".", ""))
                .collect(Collectors.toSet());
    }

    public static FileType getFileTypeByExtension(String extension) {
        String processedExt = extension.toLowerCase().replace(".", "");
        for (FileTypeMapping mapping : values()) {
            if (mapping.extensions.contains(processedExt)) {
                return mapping.fileType;
            }
        }
        throw new GlobalCustomException(ErrorCode.ILLIGAL_FILE_TYPE);
    }
}

业务代码可简化为:

FileType fileType = FileTypeMapping.getFileTypeByExtension(extension);
FileUtil.saveFile(multipartFile, historyFolder, fileType, backupFilePath);
FileUtil.saveFile(multipartFile, target, fileType, filePath);

方案二:通过配置文件动态加载扩展名映射

如果需要在不修改代码、不重启服务的情况下调整扩展名规则,可以把映射关系放到配置文件中,实现动态配置。

比如在application.yml中配置:

file-type-config:
  mappings:
    zip: ["zip"]
    image: ["jpg", "jpeg", "png", "bmp", "svg", "webp", "jfif", "pjpeg", "pjp", "apng", "avif"]

然后创建配置类读取并处理映射:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Component
@ConfigurationProperties(prefix = "file-type-config")
public class FileTypeConfig {
    private Map<String, Set<String>> mappings;
    private Map<String, FileType> extensionToType;

    @PostConstruct
    public void init() {
        extensionToType = new HashMap<>();
        mappings.forEach((typeKey, exts) -> {
            FileType fileType = FileType.valueOf(typeKey.toUpperCase());
            Set<String> processedExts = exts.stream()
                    .map(ext -> ext.toLowerCase().replace(".", ""))
                    .collect(Collectors.toSet());
            processedExts.forEach(ext -> extensionToType.put(ext, fileType));
        });
    }

    public FileType getFileTypeByExtension(String extension) {
        String processedExt = extension.toLowerCase().replace(".", "");
        FileType fileType = extensionToType.get(processedExt);
        if (fileType == null) {
            throw new GlobalCustomException(ErrorCode.ILLIGAL_FILE_TYPE);
        }
        return fileType;
    }

    // getter、setter
}

业务代码使用:

@Autowired
private FileTypeConfig fileTypeConfig;

// ...
FileType fileType = fileTypeConfig.getFileTypeByExtension(extension);
FileUtil.saveFile(multipartFile, historyFolder, fileType, backupFilePath);
FileUtil.saveFile(multipartFile, target, fileType, filePath);

方案三:策略模式+注册表,最大化扩展性

如果后续需要为不同文件类型添加更多自定义处理逻辑(不只是保存文件),策略模式可以让每种类型的处理逻辑完全独立,新增类型时无需修改原有代码,符合开闭原则。

首先定义策略接口:

public interface FileHandler {
    boolean supports(String extension);
    void handleFile(MultipartFile multipartFile, String historyFolder, String backupFilePath, String target, String filePath);
}

实现Zip和Image的处理策略:

@Component
public class ZipFileHandler implements FileHandler {
    private static final Set<String> SUPPORTED_EXTS = Set.of("zip");

    @Override
    public boolean supports(String extension) {
        String processedExt = extension.toLowerCase().replace(".", "");
        return SUPPORTED_EXTS.contains(processedExt);
    }

    @Override
    public void handleFile(MultipartFile multipartFile, String historyFolder, String backupFilePath, String target, String filePath) {
        FileUtil.saveFile(multipartFile, historyFolder, FileType.ZIP, backupFilePath);
        FileUtil.saveFile(multipartFile, target, FileType.ZIP, filePath);
    }
}

@Component
public class ImageFileHandler implements FileHandler {
    private static final Set<String> SUPPORTED_EXTS = Set.of("jpg", "jpeg", "png", "bmp", "svg", "webp", "jfif", "pjpeg", "pjp", "apng", "avif");

    @Override
    public boolean supports(String extension) {
        String processedExt = extension.toLowerCase().replace(".", "");
        return SUPPORTED_EXTS.contains(processedExt);
    }

    @Override
    public void handleFile(MultipartFile multipartFile, String historyFolder, String backupFilePath, String target, String filePath) {
        FileUtil.saveFile(multipartFile, historyFolder, FileType.IMAGE, backupFilePath);
        FileUtil.saveFile(multipartFile, target, FileType.IMAGE, filePath);
    }
}

创建注册表管理所有策略:

import org.springframework.stereotype.Component;
import java.util.List;

@Component
public class FileHandlerRegistry {
    private final List<FileHandler> fileHandlers;

    public FileHandlerRegistry(List<FileHandler> fileHandlers) {
        this.fileHandlers = fileHandlers;
    }

    public FileHandler getHandler(String extension) {
        return fileHandlers.stream()
                .filter(handler -> handler.supports(extension))
                .findFirst()
                .orElseThrow(() -> new GlobalCustomException(ErrorCode.ILLIGAL_FILE_TYPE));
    }
}

业务代码使用:

@Autowired
private FileHandlerRegistry handlerRegistry;

// ...
FileHandler handler = handlerRegistry.getHandler(extension);
handler.handleFile(multipartFile, historyFolder, backupFilePath, target, filePath);

后续新增文件类型时,只需新增一个FileHandler实现类即可,无需改动原有业务代码。


内容的提问来源于stack exchange,提问作者user19901531

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 05:46:05