Java 文件上传到服务器本地存储

一、导入相关依赖

java 复制代码
<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-all</artifactId>
	<version>5.8.35</version>
</dependency>

<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
</dependency>

二、工具类

java 复制代码
import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * File工具类,扩展 hutool 工具包
 */
@Slf4j
public class FileUtil extends cn.hutool.core.io.FileUtil {

    /**
     * 系统临时目录
     * <br>
     * windows 包含路径分割符,但Linux 不包含,
     * 在windows \\==\ 前提下,
     * 为安全起见 同意拼装 路径分割符,
     * <pre>
     *       java.io.tmpdir
     *       windows : C:\Users/xxx\AppData\Local\Temp\
     *       linux: /temp
     * </pre>
     */
    public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator;

    /**
     * 定义GB的计算常量
     */
    private static final int GB = 1024 * 1024 * 1024;

    /**
     * 定义MB的计算常量
     */
    private static final int MB = 1024 * 1024;

    /**
     * 定义KB的计算常量
     */
    private static final int KB = 1024;

    /**
     * 格式化小数
     */
    private static final DecimalFormat DF = new DecimalFormat("0.00");

    /**
     * 图片 类型
     */
    public static final String IMAGE = "Image";

    /**
     * 文档 类型
     */
    public static final String TXT = "Document";

    /**
     * 音乐 类型
     */
    public static final String MUSIC = "Music";

    /**
     * 视频 类型
     */
    public static final String VIDEO = "Video";

    /**
     * 其他 类型
     */
    public static final String OTHER = "Other";


    /**
     * MultipartFile转File
     */
    public static File toFile(MultipartFile multipartFile) {
        // 获取文件名
        String fileName = multipartFile.getOriginalFilename();
        // 获取文件后缀
        String prefix = "." + getExtensionName(fileName);
        File file = null;
        try {
            // 用uuid作为文件名,防止生成的临时文件重复
            file = new File(SYS_TEM_DIR + IdUtil.simpleUUID() + prefix);
            // MultipartFile to File
            multipartFile.transferTo(file);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return file;
    }

    /**
     * 获取文件扩展名,不带 .
     */
    public static String getExtensionName(String filename) {
        if ((filename != null) && (!filename.isEmpty())) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length() - 1))) {
                return filename.substring(dot + 1);
            }
        }
        return filename;
    }

    /**
     * Java文件操作 获取不带扩展名的文件名
     */
    public static String getFileNameNoEx(String filename) {
        if ((filename != null) && (!filename.isEmpty())) {
            int dot = filename.lastIndexOf('.');
            if (dot > -1) {
                return filename.substring(0, dot);
            }
        }
        return filename;
    }

    /**
     * 文件大小转换
     */
    public static String getSize(long size) {
        String resultSize;
        if (size / GB >= 1) {
            //如果当前Byte的值大于等于1GB
            resultSize = DF.format(size / (float) GB) + "GB";
        } else if (size / MB >= 1) {
            //如果当前Byte的值大于等于1MB
            resultSize = DF.format(size / (float) MB) + "MB";
        } else if (size / KB >= 1) {
            //如果当前Byte的值大于等于1KB
            resultSize = DF.format(size / (float) KB) + "KB";
        } else {
            resultSize = size + "B";
        }
        return resultSize;
    }

    /**
     * inputStream 转 File
     */
    static File inputStreamToFile(InputStream ins, String name) {
        File file = new File(SYS_TEM_DIR + name);
        if (file.exists()) {
            return file;
        }
        OutputStream os = null;
        try {
            os = Files.newOutputStream(file.toPath());
            int bytesRead;
            int len = 8192;
            byte[] buffer = new byte[len];
            while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            close(os);
            close(ins);
        }
        return file;
    }

    /**
     * 将文件名解析成文件的上传路径
     */
    public static File upload(MultipartFile file, String filePath) {
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS");
        // 过滤非法文件名
        String name = getFileNameNoEx(verifyFilename(file.getOriginalFilename()));
        String suffix = getExtensionName(file.getOriginalFilename());
        String nowStr = "-" + format.format(date);
        try {
            String fileName = name + nowStr + "." + suffix;
            String path = filePath + fileName;
            // getCanonicalFile 可解析正确各种路径
            File dest = new File(path).getCanonicalFile();
            // 检测是否存在目录
            if (!dest.getParentFile().exists()) {
                if (!dest.getParentFile().mkdirs()) {
                    System.out.println("was not successful.");
                }
            }
            // 文件写入
            file.transferTo(dest);
            return dest;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取文件类型
     *
     * @param type 文件名
     * @return /
     */
    public static String getFileType(String type) {
        String documents = "txt doc pdf ppt pps xlsx xls docx";
        String music = "mp3 wav wma mpa ram ra aac aif m4a";
        String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
        String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
        if (image.contains(type)) {
            return IMAGE;
        } else if (documents.contains(type)) {
            return TXT;
        } else if (music.contains(type)) {
            return MUSIC;
        } else if (video.contains(type)) {
            return VIDEO;
        } else {
            return OTHER;
        }
    }

    /**
     * 检测文件大小
     *
     * @param maxSize 最大文件大小
     * @param size    当前文件大小
     */
    public static void checkSize(long maxSize, long size) {
        // 1M
        int len = 1024 * 1024;
        if (size > (maxSize * len)) {
            throw new IllegalArgumentException("文件超出规定大小:" + maxSize + "MB");
        }
    }

    /**
     * 验证并过滤非法的文件名
     *
     * @param fileName 文件名
     * @return 文件名
     */
    public static String verifyFilename(String fileName) {
        // 过滤掉特殊字符
        fileName = fileName.replaceAll("[\\\\/:*?\"<>|~\\s]", "");

        // 去掉文件名开头和结尾的空格和点
        fileName = fileName.trim().replaceAll("^[. ]+|[. ]+$", "");

        // 不允许文件名超过255(在Mac和Linux中)或260(在Windows中)个字符
        int maxFileNameLength = 255;
        if (System.getProperty("os.name").startsWith("Windows")) {
            maxFileNameLength = 260;
        }
        if (fileName.length() > maxFileNameLength) {
            fileName = fileName.substring(0, maxFileNameLength);
        }

        // 过滤掉控制字符
        fileName = fileName.replaceAll("[\\p{Cntrl}]", "");

        // 过滤掉 ".." 路径
        fileName = fileName.replaceAll("\\.{2,}", "");

        // 去掉文件名开头的 ".."
        fileName = fileName.replaceAll("^\\.+/", "");

        // 保留文件名中最后一个 "." 字符,过滤掉其他 "."
        fileName = fileName.replaceAll("^(.*)(\\.[^.]*)$", "$1").replaceAll("\\.", "") +
                fileName.replaceAll("^(.*)(\\.[^.]*)$", "$2");

        return fileName;
    }

    /**
     * 关闭流
     */
    private static void close(Closeable closeable) {
        if (null != closeable) {
            try {
                closeable.close();
            } catch (Exception e) {
                // 静默关闭
            }
        }
    }
}

三、测试类

java 复制代码
import cn.hutool.core.util.ObjectUtil;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 文件操作测试类
 */
@SpringBootTest
public class FileUtilTests {

    @Test
    void test() throws IOException, InterruptedException {
        // 从本地读取音频文件
        Path audioPath = Paths.get("/Users/xxx/Desktop/test.mp3");
        byte[] audioContent = Files.readAllBytes(audioPath);
        MultipartFile file1 = new MockMultipartFile(
                "file",                    // 参数名(随便起,相当于接口接收参数的名字)
                "test.mp3",                      // 原始文件名
                "audio/mpeg",                    // 音频文件MIME类型(其他格式问百度查询)
                audioContent                     // 音频文件内容
        );

        // 检测文件大小
        FileUtil.checkSize(1024, file1.getSize());

        // 获取文件类型
        String suffix = FileUtil.getExtensionName(file1.getOriginalFilename());
        String type = FileUtil.getFileType(suffix);

        // 上传文件
        File file = FileUtil.upload(file1, "/Users/xxx/Desktop/" + type + File.separator);
        if (ObjectUtil.isNull(file)) {
            System.out.println("上传失败");
        } else {
            System.out.println("上传成功" + file.getPath());
            Thread.sleep(3000);
            // 删除文件
            file.delete();
        }
    }
}
相关推荐
妄想出头的工业炼药师1 小时前
cuda如何安装卸载
linux·运维·服务器
q_19132846951 小时前
基于Springboot2+Vue2的旅游景点购票系统
java·vue.js·spring boot·后端·mysql·毕业设计·计算机毕业设计
XL's妃妃1 小时前
Java 基准测试工具 JMH 详细介绍
java·开发语言·测试工具
Z3r4y1 小时前
【代码审计】RuoYi-4.7.1&4.8.1 Thymeleaf模板注入分析
java·web安全·ruoyi·代码审计·thymeleaf
serve the people1 小时前
PQ+IVF组合解决海量向量内存占用高和检索慢的问题
人工智能·python
柳鲲鹏1 小时前
LINUX下载编译libcamera
linux·运维·服务器
on_pluto_1 小时前
【debug】解决 5070ti 与 pytorch 版本不兼容的问题
人工智能·pytorch·python
嫂子的姐夫1 小时前
02-多线程
爬虫·python·多线程·并发爬虫·基础爬虫
元直数字电路验证1 小时前
Jakarta EE (原 Java EE) 技术栈概览
java·java-ee