文件上传、下载封装

文件上传、下载封装

FileUtils
package com.test.common.utils;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.test.common.utils.file.FileType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;

public abstract class FileUtils {
    
    private static final Logger log = LoggerFactory.getLogger(FileUtils.class);

    /**
     * @description  文件上传
     * @param uploadFile 上传的文件
     * @param dirPath 文件要放在哪个目录下
     * @param createFlag 如果dirPath不存在是否创建
     * */
    public static String upload(String dirPath, MultipartFile uploadFile, boolean createFlag) throws IOException {
        Assert.isTrue(StrUtil.isNotEmpty(dirPath), "dirPath不能为空");
        Assert.isTrue(ObjectUtil.isNotNull(uploadFile), "file不能为空");

        // 校验文件是否符合规范
        String originalFilename = uploadFile.getOriginalFilename();
        String[] strs = originalFilename.split(".");
        String suffix = strs[strs.length - 1];
        FileType fileType = FileType.getBySuffixName(suffix);

        if(!isNormative(fileType, uploadFile.getBytes())) {
            throw new IllegalArgumentException(String.format("文件内容与文件类型不匹配"));
        }

        String chineseChar = hasChinese(dirPath);
        Assert.isTrue(StrUtil.isEmpty(chineseChar),String.format("dirPath包含中文字符[%s]",chineseChar));

        final String tempPath = dirPath;

        String osName = SystemUtils.judgeSystem();

        // 校验dirPath中是否包含不属于当前操作系统的路径分隔符
        SystemUtils.SystemType[] systemTypes = SystemUtils.SystemType.values();
        boolean matchResult = Arrays.stream(systemTypes).filter(systemType -> !systemType.getTypeName().equalsIgnoreCase(osName))
            .anyMatch(systemType -> tempPath.contains(systemType.getFileSeparator()));
        if(matchResult) {
            throw new IllegalArgumentException("dirPath中包含不属于当前操作系统的路径分隔符");
        }

        dirPath = dirPath + (dirPath.endsWith(File.separator) ? "" : File.separator);

        File file = new File(dirPath);
        boolean isExists = file.exists();

        if(isExists) {
            if(!file.isDirectory()) {
                throw new IllegalArgumentException(String.format("存在%s,但是类型不是目录",dirPath));
            }
        } else {
            if(!createFlag) {
                throw new IllegalArgumentException(String.format("目标路径[%s]不存在",dirPath));
            }
            // 创建目录
            boolean mkResult = file.mkdir();
            if(!mkResult) {
                throw new RuntimeException(String.format("目录[%s]创建失败",dirPath));
            }
        }

        String newFileName = "TEST_UPLOAD" + uploadFile.getOriginalFilename() + DateUtil.format(new Date(), "yyyy-MM-dd") + UUID.randomUUID();
        
        String newFileFullName = dirPath + newFileName;

        ByteBuffer buffer = ByteBuffer.allocate(10240);
        ReadableByteChannel readChannel = Channels.newChannel(uploadFile.getInputStream());
        File newFile = new File(newFileFullName);
        if(!newFile.exists()) {
            if(!newFile.createNewFile()) {
                throw new RuntimeException(String.format("文件[%s]创建失败"));
            }
        }
        FileChannel writeChannel = new FileOutputStream(newFile).getChannel();
        while (readChannel.read(buffer) != -1) {
            buffer.flip();
            writeChannel.write(buffer);
            buffer.clear();
        }
        writeChannel.close();
        readChannel.close();

        return newFileFullName;
    }


    /**
     * 校验文件是否符合魔法数规范
     * @param fileType
     * @param bytes
     * */
    public static boolean isNormative(FileType fileType, byte[] bytes) {
        List<String> magicNumbers = fileType.getMagicNumbers();
        int[] magicNumberLength = fileType.getMagicNumberLength();
        for(int i = 0;i < magicNumberLength.length; i++) {
            int contentLength = magicNumberLength[i];
            byte[] content = new byte[contentLength];
            for(int j = 0;j < contentLength;j++) {
                content[j] = bytes[j];
            }
            StringBuilder stringBuilder = new StringBuilder();
            for(int j=0;j<content.length;j++) {
                int val = content[j] & 0XFF;
                String hexVal = Integer.toHexString(val);
                if(hexVal.length() < 2) {
                    stringBuilder.append("0");
                }
                stringBuilder.append(hexVal);
            }
            if(!stringBuilder.toString().equals(magicNumbers.get(i))) {
                return false;
            }
        }
        return true;
    }


    /**
     * @description 校验是否存在中文
     * @param path 路径
     * @return 中文字符
     * */
    public static String hasChinese(String path) {
        Assert.isTrue(StrUtil.isNotEmpty(path),"path不能为空");
        char[] charArr = path.toCharArray();
        for(int i = 0; i<charArr.length; i++) {
            char val = charArr[i];
            if(((int)val) > 127) {
                return String.valueOf(val);
            }
        }
        return null;
    }

}
FileType
package com.test.common.utils.file;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.util.Assert;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public enum FileType {

    /**
     * JPEG
     * */
    JPEG("JPEG", Stream.of("FFD8FF").collect(Collectors.toList()), new int[]{3},Stream.of(".jpg",".jpeg",".jpe",".jfif",".exif").collect(Collectors.toList())),

    /**
     * PNG
     * */
    PNG("PNG",Stream.of("89504E470D0A1A0A").collect(Collectors.toList()), new int[]{8},Stream.of(".png").collect(Collectors.toList())),

    /**
     * GIF
     * */
    GIF("GIF",Stream.of("474946383961","4749383761").collect(Collectors.toList()), new int[]{6,6},Stream.of(".gif").collect(Collectors.toList())),

    /**
     * BMP
     * */
    BMP("BMP",Stream.of("424D").collect(Collectors.toList()), new int[]{2},Stream.of(".bmp",".dib").collect(Collectors.toList())),

    /**
     * TIFF
     * */
    TIFF("TIFF",Arrays.asList("4D4D002A","49492A00"),new int[]{4,4},Arrays.asList(".tif",".tiff")),

    /**
     * WORD
     * */
    WORD("WORD",Arrays.asList("D0CF11E0A1B11AE1"),new int[]{8},Arrays.asList(".doc")),

    /**
     * WORD_XML
     * */
    WORD_XML("WORD_XML",Arrays.asList("504B0304"),new int[]{4},Arrays.asList(".docx",".docm",".dotx",".dotm")),

    /**
     * PPT
     * */
    PPT("PPT",Arrays.asList("D0CF11E0A1B11AE1"),new int[]{8},Arrays.asList(".ppt")),

    /**
     * PPT_XML
     * */
    PPT_XML("PPT_XML",Arrays.asList("504B0304"),new int[]{4},Arrays.asList(".pptx",".pptm",".potx",".potm")),

    /**
     * EXCEL
     * */
    EXCEL("EXCEL",Arrays.asList("D0CF11E0A1B11AE1"),new int[]{8},Arrays.asList(".xls")),

    /**
     * EXCEL_XML
     * */
    EXCEL_XML("EXCEL_XML",Arrays.asList("504B030414000600"),new int[]{8},Arrays.asList(".xlsx",".xlsm",".xlsb",".xltx")),

    /**
     * EXCEL_XLT
     * */
    EXCEL_XLT("EXCEL_XLT",Arrays.asList("D0CF11E0A1B11AE1"),new int[]{8},Arrays.asList(".xlt")),

    /**
     * TXT
     * */
    TXT("TXT",Arrays.asList(".txt",".text"));




    // 文件类型
    private String fileType;

    // 文件类型所有的魔法数
    private List<String> magicNumbers;

    // 魔法数的字节长度
    private int[] magicNumberLength;

    // 文件类型所有的后缀名
    private List<String> suffixNames;

    FileType(String fileType, List<String> magicNumbers, int[] magicNumberLength, List<String> suffixNames) {
        Assert.isTrue(StrUtil.isNotEmpty(fileType),"fileType不能为空");
        Assert.isTrue(CollUtil.isNotEmpty(magicNumbers),"magicNumbers不能为空");
        Assert.isTrue(null != magicNumberLength && magicNumberLength.length > 0 && magicNumberLength.length == magicNumbers.size(),
            "magicNumberLength不能为空且长度必须等于magicNumbers的个数");
        Assert.isTrue(CollUtil.isNotEmpty(suffixNames),"suffixNames不能为空");
        this.fileType = fileType;
        this.magicNumbers = magicNumbers;
        this.magicNumberLength = magicNumberLength;
        this.suffixNames = suffixNames;
    }

    FileType(String fileType, List<String> suffixNames) {
        Assert.isTrue(StrUtil.isNotEmpty(fileType),"fileType不能为空");
        Assert.isTrue(CollUtil.isNotEmpty(suffixNames),"suffixNames不能为空");
        this.fileType = fileType;
        this.suffixNames = suffixNames;
    }


    public String getFileType() {
        return fileType;
    }

    public List<String> getMagicNumbers() {
        return magicNumbers;
    }

    public int[] getMagicNumberLength() {
        return magicNumberLength;
    }

    public List<String> getSuffixNames() {
        return suffixNames;
    }

    /**
     * 根据文件后缀名获取FileType
     * @param fileSuffixName 文件后缀名
     * */
    public static FileType getBySuffixName(String fileSuffixName) {
        if(!isSupported(fileSuffixName)) {
            throw new IllegalArgumentException(String.format("暂不支持处理该类型的文件[%s]",fileSuffixName));
        }
        FileType[] arr = values();
        List<FileType> fileTypeList = Arrays.stream(arr).filter(val->val.suffixNames.contains(fileSuffixName)).collect(Collectors.toList());
        if(fileTypeList.size() > 1) {
            throw new IllegalArgumentException(String.format("文件类型存在错误[%s]",fileSuffixName));
        }
        return fileTypeList.get(0);
    }


    /**
     * 验证文件类型是否支持
     * @param fileSuffixName 文件后缀名
     * */
    public static boolean isSupported(String fileSuffixName) {
        FileType[] arr = values();
        return Arrays.stream(arr).anyMatch(val->val.suffixNames.contains(fileSuffixName));
    }



}


你可能感兴趣的:(java)