文件上传与下载

工具:hutool

springboot 文件上传与下载,hutool目录操作、文件解压、yaml文件操作。此例子展示了一个文件压缩包上传到服务器,解压放到某个特定目录的,并且校验md5值

html

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传界面</title>
</head>
<body>
<div>
    <form method="POST" enctype="multipart/form-data" action="/upload">
        <table>
            <tr>
                <td><input type="file" name="file"/></td>
            </tr>
            <tr>
                <td></td>
                <td><input type="submit" value="上传"/></td>
            </tr>
        </table>
    </form>
​
    <a href="http://localhost:8080/download" download> file_name </a>
​
</div>
</body>
</html>

springboot

上传

    /**
     * 规定,一个归档文件比如叫 1.1.1.2023.tar 这个归档文件里面有两个文件一个叫:upgrade-info.yml 一个叫:1.1.1.2023.tar.gz
     * 这个归档文件放到 /device-upgrade-pack-repo/1.1.1.2023 文件夹,然后将归档文件在此目录解压,然后删除归档文件
     * 最终目录结构为:
     * /device-upgrade-pack-repo/1.1.1.2023
     * |--> 1.1.1.2023.tar.gz
     * |--> upgrade-info.yml
     * |--> 1.1.1.2023.tar
     *
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public AjaxResult upload(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return error("文件不能为空");
        }
        String filename = file.getOriginalFilename();
        // 文件大概名字为:1.1.1.2023.tar ,不要 .tar 后缀
        String versionNum = filename.substring(0, filename.length() - 4);
        // jar包的上一级目录
        String canonicalPath = FileUtil.getCanonicalPath(new File(".."));
        // 创建目录
        String directory = canonicalPath + "/device-upgrade-pack-repo/" + versionNum;
        FileUtil.mkdir(directory);
        // 将文件放到目录
        String filePath = directory + "/" + filename;
        try {
            // 此方法是,如果文件已经存在,那么会删除老的,然后用新的文件
            file.transferTo(new File(filePath));
        } catch (IOException e) {
            throw new ServiceException("文件上传失败");
        }
        // 解压
        Extractor extractor = CompressUtil.createExtractor(
                CharsetUtil.defaultCharset(),
                FileUtil.file(filePath));
​
        extractor.extract(FileUtil.file(directory));
​
        // 读取upgrade-info.yml 文件, 对比md5,如果不正确则返回错误,并删除目录
        Yaml yaml = new Yaml();
        BufferedInputStream inputStream = FileUtil.getInputStream(directory + "/upgrade-info.yml");
        Map<String, Object> obj = yaml.load(inputStream);
        try {
            inputStream.close();
        } catch (IOException e) {
            throw new ServiceException("读取upgrade-info.yml异常,查看文件是否存在");
        }
        String md5 = (String) obj.get("md5");
        String version = (String) obj.get("versionNum");
        String devType = (String) obj.get("devType");
        // 校验md5值
        String digestHex = SecureUtil.md5().digestHex(FileUtil.file(filePath + ".gz"));
​
        // 如果md5值不相等
        if (!StringUtils.equals(md5, digestHex)) {
            log.info("md5 {} digestHex {}", md5, digestHex);
            // 删除目录,并且返回错误
            boolean del = FileUtil.del(directory);
            if (del) {
                return error("压缩包与yml文件中校验码不一致,请确认升级包是否正确");
            } else {
                return error("压缩包与yml文件中校验码不一致,且上传的文件删除失败,请联系系统管理员");
            }
        }
        // 返回upgrade-info.yml 中的信息
        JSONObject res = new JSONObject();
        res.put("versionNum", version);
        res.put("checkCode", md5);
        res.put("devType", devType);
        return success(res);
    }

下载

根据一定规则找到文件目录,然后进行下载

"Content-disposition: attachment;filename=" + versionNum + ".tar" 这个的作用是设置下载的文件的名字,比如说versionNum的值为1.1.0,那么下载文件的名字为1.1.0.tar

    @SneakyThrows
    @GetMapping("/download")
    public void download(HttpServletResponse response, @RequestParam String versionNum) {
        if (StringUtils.isEmpty(versionNum)) {
            throw new ServiceException("版本号不能为空");
        }
        // jar包的上一级目录
        String canonicalPath = FileUtil.getCanonicalPath(new File(".."));
        String filePath = canonicalPath + "/device-upgrade-pack-repo/" + versionNum + "/" + versionNum + ".tar";
​
        BufferedInputStream stream = FileUtil.getInputStream(filePath);
​
        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition",
                "attachment;filename=" + versionNum + ".tar");
        // Read the input stream and print to the console till EOF.
        byte[] buf = new byte[16384];
        int bytesRead;
        while ((bytesRead = stream.read(buf, 0, buf.length)) >= 0) {
            response.getOutputStream().write(buf, 0, bytesRead);
        }
        stream.close();
    }
09-06 11:39