批量文件压缩下载(zip)

ps:工作之余仅留备份用,未全面完善,请按需取用

一、主要关注两点:1.找到文件并压缩;2.通过文件输出流响应前端


@RestController
@RequestMapping("/file")
public class FileController extends BaseController {

    @Autowired
    private StorageServerService storageServerService;
    @Autowired
    private FileInfoService fileInfoService;
    @Autowired
    private CompactFileService compactFileService;

    @Autowired
    private Environment env;

    /**
     * 上传文件
     */
    @RequestMapping("/upload")
    public SysMsgItems<Object> upload(MultipartFile file) throws IOException {
        StorageServer server = storageServerService.getStorageServer();
        String fileUrl = DateUtils.formatDate(new Date(), "yyyyMMdd");
        if (!Files.exists(Paths.get(server.getStorageDir() + File.separator + fileUrl))) {
            Files.createDirectories(Paths.get(server.getStorageDir() + File.separator + fileUrl));
        }
        String fileName = file.getOriginalFilename();
        String _fileName = UUID.randomUUID().toString();
        if (fileName.lastIndexOf(".") >= 0) {
            _fileName = _fileName + fileName.substring(fileName.lastIndexOf("."));
        }
        fileUrl = fileUrl + File.separator + _fileName;
        File f = new File(server.getStorageDir() + File.separator + fileUrl);
        OutputStream os = new FileOutputStream(f);
        long fileSize = IOUtils.copyLarge(file.getInputStream(), os);
        IOUtils.closeQuietly(os);
        InputStream in = new FileInputStream(f);
        String md5 = DigestUtils.md5DigestAsHex(in);
        in.close();
        String fId = fileInfoService.create(fileName, fileSize, md5, server.getId(), fileUrl);
        SysMsgItems<Object> result = new SysMsgItems<Object>();
        result.setItems(new ParamUtils.ParamBuilder()
                .set("success", true)
                .set("fileUrl", fileUrl)
                .set("fileSize", fileSize)
                .set("fId", fId)
                .build());
        return result;
    }

    /**
     * 下载文件
     */
    @RequestMapping("/download")
    public void download1(String fileUrl, String size, String fileName, HttpServletResponse response) {
        InputStream inStream = null;
        OutputStream os = null;
        try {
            String fileStorageUrl = fileInfoService.getFileStoragePathByFileUrl(fileUrl);
            if (!ObjectUtils.isEmpty(fileStorageUrl)) {
                inStream = new FileInputStream(fileStorageUrl);
                String encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
                response.addHeader("Content-Length", "" + size);
                if (fileName.toLowerCase().endsWith("pdf")) {
                    response.setContentType("application/pdf");
                    response.setHeader("Content-Disposition", "inline;filename=\"" + encodedFileName + "\";filename*=utf-8''" + encodedFileName);
                } else {
                    response.setContentType("application/octet-stream");
                    response.setHeader("Content-Disposition", "attachment;filename=\"" + encodedFileName + "\";filename*=utf-8''" + encodedFileName);
                }
                os = new BufferedOutputStream(response.getOutputStream());
                byte[] buffer = new byte[1024];
                int count = 0;
                while ((count = inStream.read(buffer)) >= 0) {
                    os.write(buffer, 0, count);
                    os.flush();
                }
            } else {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            }
        } catch (Exception e) {
            logger.error(ExceptionCollect.collectExceptionStackMsg(e));
        } finally {
            try {
                os.flush();
                inStream.close();
            } catch (Exception e2) {
                logger.error(ExceptionCollect.collectExceptionStackMsg(e2));
            }
        }
    }

    /**
     * 批量文件压缩下载
     *
     * @author wangxy2
     * @since 2022/4/22
     */
    @RequestMapping("/downloadByCompact")
    public void downloadByCompact(@RequestBody Map<Object, Object> params, HttpServletResponse response) {
        OutputStream os = null;
        ZipOutputStream out = null;
        try {
            String businessNum = ParamUtils.getString(params, "businessNum", String.format("%s_batch", UserPrincipalUtils.getUserPrincipal().getUserName())),
                    encodedFileName = java.net.URLEncoder.encode(businessNum + ".zip", "utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=\"" + encodedFileName + "\";filename*=utf-8''" + encodedFileName);
            response.setContentType("application/octet-stream");
            // 创建zip输出流
            out = new ZipOutputStream(response.getOutputStream());
            // 创建缓冲输出流
            os = new BufferedOutputStream(out);

            List<Map<Object, Object>> fileInfoList = (List<Map<Object, Object>>) params.get("fileInfoList");
            for (Map<Object, Object> fileInfoMap : fileInfoList) {
                String fileUrl = ParamUtils.getString(fileInfoMap, "fileUrl", ""),
                        fileName = ParamUtils.getString(fileInfoMap, "fileName", "");
                // 此处是获取文件的物理绝对地址
                String fileStorageUrl = fileInfoService.getFileStoragePathByFileUrl(fileUrl);

                // 压缩单个文件
                File srcfile = new File(fileStorageUrl);
                compactFileService.compress(srcfile, out, "", fileName);
            }
            os.flush();
            logger.info("==批量文件压缩完毕==");
        } catch (Exception e) {
            logger.error("==批量文件压缩下载失败,原因:{}==", e.getMessage());
        } finally {
            try {
                if (os != null) {
                    os.flush();
                }
                if (out != null) {
                    out.close();
                }
            } catch (Exception e2) {
                logger.error("==批量文件压缩下载-关闭流失败,原因:{}==", e2.getMessage());
            }
        }
    }
}

二、此处更关注的是:文件的物理绝对地址并不是源文件名称,需要在压缩的时候,指定压缩条目(文件)名称

package cn.qh.filecenter.files.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 压缩文件
 *
 * @author wangxy2
 * @since 2022/4/22
 */
@Service("compactFileService")
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public class CompactFileService {
    private static Logger logger = LoggerFactory.getLogger(CompactFileService.class);

    /**
     * 压缩文件夹里的文件
     * 起初不知道是文件还是文件夹--- 统一调用该方法
     */
    public void compress(File file, ZipOutputStream out, String basedir) {
        /* 判断是目录还是文件 */
        if (file.isDirectory()) {
            this.zipDirectory(file, out, basedir);
        } else {
            this.zipFile(file, out, basedir);
        }
    }

    /**
     * 压缩文件夹
     */
    public void zipDirectory(File dir, ZipOutputStream out, String basedir) {
        if (!dir.exists()) {
            return;
        }

        File[] files = dir.listFiles();
        for (int i = 0; i < files.length; i++) {
            compress(files[i], out, basedir + dir.getName() + "/");
        }
    }

    /**
     * 压缩单个文件
     */
    public void zipFile(File srcfile, ZipOutputStream out, String basedir) {
        if (!srcfile.exists()) {
            return;
        }

        byte[] buf = new byte[1024];
        FileInputStream in = null;

        try {
            int len;
            in = new FileInputStream(srcfile);
            out.putNextEntry(new ZipEntry(basedir + srcfile.getName()));

            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.closeEntry();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /*-------------- 指定fileName --------------------*/

    /**
     * 压缩文件夹里的文件(使用指定的名称创建新的zip文件)
     * 起初不知道是文件还是文件夹--- 统一调用该方法
     */
    public void compress(File file, ZipOutputStream out, String basedir, String fileName) {
        if (file.isDirectory()) {
            /* 当前file是目录,需要循环遍历 */
            this.zipDirectory(file, out, basedir);
        } else if (ObjectUtils.isEmpty(fileName)) {
            // 没有指定文件名称,使用文件物理地址文件名
            this.zipFile(file, out, basedir);
        } else {
            this.zipFile(file, out, basedir, fileName);
        }
    }


    /**
     * 压缩单个文件(使用指定的名称创建新的zip文件)
     */
    public void zipFile(File srcfile, ZipOutputStream out, String basedir, String fileName) {
        if (!srcfile.exists()) {
            return;
        }

        byte[] buf = new byte[1024];
        FileInputStream in = null;

        try {
            int len;
            in = new FileInputStream(srcfile);
            // ZipEntry: Creates a new zip entry with the specified name.
            out.putNextEntry(new ZipEntry(basedir + fileName));

            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.closeEntry();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值