檔案下載與上傳

2023-09-06 12:00:23

檔案上傳與下載

工具: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();
    }