文件资源管理器---文件类型的一些问题

由于自身项目需要,需要实现一个文件资源管理器,为了UI的美观,必须根据文件类型加载对应的SVG图片,那么如何确定文件类型呢?

1.匹配文件类型

这里我主要使用Files.probeContentType()静态函数获取文件的MIME类型,如果你非要使用文件尾缀,可以不要看下面了,按你自己的想法来

首先贴上完整枚举类,用枚举类对象表示文件类型


import lombok.Getter;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;

/**
 * @Classname FileType
 * @Description 文件类型枚举
 * @Version 1.0.0
 * @Date 2024/9/23 23:03
 * @Created by sinevil
 */
@Getter
public enum FileType {
    Directory("application/x-directory"),



    //文本文件
    TXT("text/plain"),
    PDF("application/pdf"),
    DOC("application/msword"),
    DOCX("application/vnd.openxmlformats - officedocument.wordprocessingml.document"),
    RTF("text/rtf"),

    // 压缩文件
    ZIP("application/zip"),
    RAR("application/x-rar-compressed"),
    Z7("application/x-7z-compressed"),
    TAR("application/x-tar"),
    GZ("application/gzip"),
    BZ2("application/x - bzip2"),

    //可执行文件
    EXE("application/octet-stream"),
    BAT("application/bat"),
    SH("application/x-shellscript"),
    MSI("application/x-msi"),

    //表格文件
    XLS("application/vnd.ms-excel"),
    XLSX("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
    CSV("text/csv"),
    ODS("application/vnd.oasis.opendocument.spreadsheet"),

    //演示文稿文件
    PPT("application/vnd.ms-powerpoint"),
    PPTX("application/vnd.openxmlformats - officedocument.presentationml.presentation"),
    ODP("application/vnd.oasis.opendocument.presentation"),

    JSON("application/json"),
    DLL("application/x-msdownload"),

    HTML("text/html"),
    XML("text/xml"),

    AUDIO("audio/*"),
    VIDEO("video/*"),
    IMAGE("image/*"),

    OTHER("*/*");
    private final String mimeType;

    FileType(String mimeType) {
        this.mimeType = mimeType;
    }

    // 新增的用于存储带通配符的FileType列表
    private static final Map<String,FileType> RegexPatternMap  = new HashMap<>();
    static {
        // 在类加载时初始化将带通配符的FileType列表
        String var;
        for (FileType fileType : values()) {
            if (fileType != FileType.OTHER) {
                var = fileType.mimeType;
                if (var.contains("*")) {
                    RegexPatternMap.put(transformToRegex(var), fileType);
                }
            }
        }
    }

    /**
     * 转化带*号的字符串,将其转化为正则表达式
     * "audio/*" "audio/.*"
     *
     * @param var1 含有*的字符串
     * @return
     */
    private static String transformToRegex(String var1){
        int asteriskIndex = var1.indexOf("*");
        if (asteriskIndex+1 < var1.length())
            return var1.substring(0, asteriskIndex) + ".*" + transformToRegex(var1.substring(asteriskIndex+1));
        else return var1.substring(0, asteriskIndex) + ".*";
    }

    public static FileType fromMimeType(String mimeType) {
        if (mimeType != null){
            // 使用正则进行匹配
            for (String regex : RegexPatternMap.keySet()) {
                if (mimeType.matches(regex))
                    return RegexPatternMap.get(regex);
            }

            for (FileType fileType : values()) {
                String type = fileType.getMimeType();
                if (type.equals(mimeType))
                    return fileType;
            }

            return OTHER;
        }
        return OTHER;
    }

    /**
     * 根据Path对象获取MIMETYPE字符串
     * @param path
     * @return
     */
    public static FileType getFileType(Path path){
        if (Files.isDirectory(path))
            return FileType.Directory;

        try {
            return FileType.fromMimeType(Files.probeContentType(path));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 根据File对象获取MIMETYPE字符串
     * @return
     */
    public static FileType getFileType(File file){
        return getFileType(file.toPath());
    }


}

枚举类的核心是

    public static FileType fromMimeType(String mimeType) {
        if (mimeType != null){
            // 使用正则进行匹配
            for (String regex : RegexPatternMap.keySet()) {
                if (mimeType.matches(regex))
                    return RegexPatternMap.get(regex);
            }

            for (FileType fileType : values()) {
                String type = fileType.getMimeType();
                if (type.equals(mimeType))
                    return fileType;
            }

            return OTHER;
        }
        return OTHER;
    }

根据传入的MEME类型字符串返回对应的FileType对象,这里先对传入的memeType进行非空判断,因为Java自带的Mime类型获取器支持的类型比较少,当遇到不支持的类型时,Files.probeContentType()会返回null。之后首先对能够进行通配的Audio、Video、Image类型的文件进行匹配,之后再对不能统配的进行匹配。

2. 根据文件类型创建对象

获取文件类型后就需要根据文件类型创建对应的对象

/**
 * @Classname FileInfoFactory
 * @Description 文件信息工厂,用于根据文件类型创建对应的信息类对应
 * @Version 1.0.0
 * @Date 2024/11/25 21:46
 * @Created by sinevil
 */
public class FileInfoFactory {
    // 使用Map来存储文件类型与对应的创建信息类对象的函数
    private static final Map<FileType, Supplier<? extends BasicInfo>> FILE_TYPE_TO_CREATOR_MAP = new HashMap<>();

    static {
        // 初始化Map,将每个文件类型与对应的创建函数关联起来
        FILE_TYPE_TO_CREATOR_MAP.put(FileType.Directory, CatalogueInfo::new);

        FILE_TYPE_TO_CREATOR_MAP.put(FileType.VIDEO,VideoFileInfo::new);
        FILE_TYPE_TO_CREATOR_MAP.put(FileType.AUDIO,AudioFileInfo::new);
        FILE_TYPE_TO_CREATOR_MAP.put(FileType.IMAGE,ImageFileInfo::new);

        //文本文件
        FILE_TYPE_TO_CREATOR_MAP.put(FileType.TXT, TextInfo::new);
        FILE_TYPE_TO_CREATOR_MAP.put(FileType.PDF, TextInfo::new);
        FILE_TYPE_TO_CREATOR_MAP.put(FileType.DOC, TextInfo::new);
        FILE_TYPE_TO_CREATOR_MAP.put(FileType.DOCX, TextInfo::new);
        FILE_TYPE_TO_CREATOR_MAP.put(FileType.RTF, TextInfo::new);




    }

    public static BasicInfo createFileInfoObject(Path path){
        FileType fileType = FileType.getFileType(path);
        Supplier<? extends BasicInfo> creator = FILE_TYPE_TO_CREATOR_MAP.get(fileType);
        if (creator == null) {
            // 如果没有找到对应的创建函数,默认创建BasicFileInfo对象
            return new BasicInfo(path);
        }
        return creator.get().init(path);
    }
}

这里需要用到Map,以FileType对象为键,对应信息类的构造函数为值,当传入一个路径时会先获取其fileType ,然后通过map获取静态绑定好的构造函数,并获取对象。

可以使多个FileType类型对应一个Info,因为文件的属性就那些,这里贴上文件的基本信息类。

对于图片视频等不可修改文件可以通过继承添加“最后访问时间”属性,对于文本等可修改文件,则添加“最后访问时间”和“最后修改时间”属性。

@Data
@AllArgsConstructor
public class BasicInfo implements SVGOperate {

    protected static Map<String,String> SVGMap = new HashMap<>();

    protected Path path;
    protected BasicFileAttributes attributes;
    protected String absolutePath;
    protected String name;
    protected FileType fileType;
    protected String type;
    protected Long size;
    protected Boolean isDirectory;
    protected LocalDateTime creationTime;

    static {
        SVGMap.put("unknown","imgs/svg/file/unknown.svg");
    }

    public BasicInfo(Path path){
        this.path = path;
        this.absolutePath = path.toString();

        this.name = String.valueOf(path.getFileName());
        if (Objects.equals(this.name, "null"))
            this.name = path.toString();

        try {
            this.attributes = Files.readAttributes(path, BasicFileAttributes.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        this.size = this.attributes.size();
        this.isDirectory = attributes.isDirectory();

        if (this.isDirectory){
            this.fileType = FileType.Directory;
            this.type = "directory";
        }
        else {
            this.fileType = FileType.getFileType(path);
            this.type = getFileExtension(this.path);
        }

        this.creationTime = LocalDateTime.ofInstant(this.attributes.creationTime().toInstant(), ConfigConstant.ZONEID);

    }

    public BasicInfo(){}

    /**
     * 使用空参构造方法创建对象时调用此方法初始化类对象
     * @param path
     */
    public BasicInfo init(Path path){
        this.path = path;
        this.absolutePath = path.toString();

        this.name = String.valueOf(path.getFileName());
        if (Objects.equals(this.name, "null"))
            this.name = path.toString();

        try {
            this.attributes = Files.readAttributes(path, BasicFileAttributes.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        this.size = this.attributes.size();
        this.isDirectory = attributes.isDirectory();

        if (this.isDirectory){
            this.fileType = FileType.Directory;
            this.type = "directory";
        }
        else {
            this.fileType = FileType.getFileType(path);
            this.type = getFileExtension(this.path);
        }

        return this;
    }

    public String getSVG(){
        return SVGMap.get("unknown");
    }
    protected String getSVG(String type){
        String svg;
        svg = SVGMap.get(type);
        if (svg==null)
            return getSVG();
        return svg;
    }


    /**
     * 根据Path对象获取文件的后缀名
     * 如果是目录文件则返回"directory"
     * @param path
     * @return
     */
    public static String getFileExtension(Path path) {
        String fileName = String.valueOf(path.getFileName());
        int lastIndexOfDot = fileName.lastIndexOf('.');
        if (lastIndexOfDot > 0 && lastIndexOfDot < fileName.length() - 1) {
            return fileName.substring(lastIndexOfDot + 1);
        }
        return "directory";
    }

    /**
     * 返回当前文件是否是目录
     * @return
     */
    public boolean isDirectory(){
        return this.isDirectory;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值