多文件批量压缩下载,单文件夹压缩下载

现有一个新需求,用户可选择多个文件,多文件批量压缩下载,由于传统的代码效率不高,网上查询资料,对部分内容进行了修改与整合,特此留档

一、导入依赖

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-compress</artifactId>
    <version>1.19</version>
</dependency>

二、创建HighEffiCompressZip工具类

将下面工具类中的内容直接复制即可

public class HighEffiCompressZip {
    private String rootPaths;

    ParallelScatterZipCreator scatterZipCreator = new ParallelScatterZipCreator();
    // ParallelScatterZipCreator api says:
    // 注意这个类不保证写入到输出文件的顺序。需要保持特定顺序的(manifests,文件夹)必须使用这个类的客户类进行处理
    // 通常的做法是 在调用这个类的writeTo方法前把这些东西写入到ZipArchiveOutputStream
    ScatterZipOutputStream dirs = ScatterZipOutputStream
            .fileBased(File.createTempFile("whatever-preffix", ".whatever"));


    public HighEffiCompressZip(String rootPaths) throws IOException {
        this.rootPaths = rootPaths;
    }

    public HighEffiCompressZip() throws IOException {
    }


    public void addEntry(final ZipArchiveEntry zipArchiveEntry, final InputStreamSupplier streamSupplier)
            throws IOException {
        if (zipArchiveEntry.isDirectory() && !zipArchiveEntry.isUnixSymlink()) {
            dirs.addArchiveEntry(ZipArchiveEntryRequest.createZipArchiveEntryRequest(zipArchiveEntry, streamSupplier));
        } else {
            scatterZipCreator.addArchiveEntry(zipArchiveEntry, streamSupplier);
        }
    }


    public void writeTo(final ZipArchiveOutputStream zipArchiveOutputStream)
            throws IOException, ExecutionException, InterruptedException {
        dirs.writeTo(zipArchiveOutputStream);
        dirs.close();
        scatterZipCreator.writeTo(zipArchiveOutputStream);
    }


    public String getRootPaths() {
        return rootPaths;
    }

    public void setRootPaths(String rootPath) {
        this.rootPaths = rootPaths;
    }
}

三、创建HighEffiCompressZipTest类内容

1、公共方法

@RestController
public class HighEffiCompressZipTest {

    class CustomInputStreamSupplier implements InputStreamSupplier {
        private File currentFile;


        public CustomInputStreamSupplier(File currentFile) {
            this.currentFile = currentFile;
        }


        @Override
        public InputStream get() {
            try {
                // InputStreamSupplier api says:
                // 返回值:输入流。永远不能为Null,但可以是一个空的流
                return new FileInputStream(currentFile);
//                return currentFile.isDirectory() ? new NullInputStream(0) : new FileInputStream(currentFile);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }
    }


    private void  addEntry(String entryName, File currentFile, HighEffiCompressZip scatterSample) throws IOException {
        ZipArchiveEntry archiveEntry = new ZipArchiveEntry(entryName);
        archiveEntry.setMethod(ZipEntry.DEFLATED);
        final InputStreamSupplier supp = new CustomInputStreamSupplier(currentFile);
        scatterSample.addEntry(archiveEntry, supp);
    }

    private void addEntryOneDir(String entryName, File currentFile, HighEffiCompressZip scatterSample) throws IOException {
        ZipArchiveEntry archiveEntry = new ZipArchiveEntry(entryName);
        archiveEntry.setMethod(ZipEntry.DEFLATED);
        final InputStreamSupplier supp = new CustomInputStreamSupplier(currentFile);
        scatterSample.addEntry(archiveEntry, supp);
    }


    private void compressCurrentDirectory(List<String> dir, HighEffiCompressZip scatterSample) throws IOException {
        if (dir == null) {
            throw new IOException("源路径不能为空!");
        }
        String relativePath = "";
//       // if (dir.isFile()) {
//           // relativePath = dir.getName();
//            addEntry("download", null, scatterSample);
//            return;
//        }


//        // 空文件夹
//        if (dir.listFiles().length == 0) {
//            relativePath = dir.getAbsolutePath().replace(scatterSample.getRootPath(), "");
//            addEntry(relativePath + File.separator, dir, scatterSample);
//            return;
//        }
        for (String file : dir) {
            File f = new File(file);
            if (!f.isDirectory()){
                addEntry(f.getName(), f, scatterSample);//此种写法是多种文件压缩到一个文件夹中
//                relativePath = f.getParent().replace(scatterSample.getRootPaths(), "");
//                addEntry(relativePath + File.separator + f.getName(), f, scatterSample);//此种写法是压缩包中包括文件夹路径
            }
        }
    }

	private void compressCurrentDirectoryOneDir(File dir, HighEffiCompressZip scatterSample) throws IOException {
        if (dir == null) {
            throw new IOException("源路径不能为空!");
        }
        String relativePath = "";
        if (dir.isFile()) {
            relativePath = dir.getName();
            addEntryOneDir(relativePath, dir, scatterSample);
            return;
        }

        // 空文件夹
        if (dir.listFiles().length == 0) {
            relativePath = dir.getAbsolutePath().replace(scatterSample.getRootPaths(), "");
            addEntryOneDir(relativePath + File.separator, dir, scatterSample);
            return;
        }
        for (File f : dir.listFiles()) {
            if (f.isDirectory()) {
                compressCurrentDirectoryOneDir(f, scatterSample);
            } else {
                relativePath = f.getParent().replace(scatterSample.getRootPaths(), "");
                addEntryOneDir(relativePath + File.separator + f.getName(), f, scatterSample);
            }
        }
    }

	private void compressCurrentDirectoryTree(List<String> dir, HighEffiCompressZip scatterSample) throws IOException {
        if (dir == null) {
            throw new IOException("源路径不能为空!");
        }
        String relativePath = "";
//       // if (dir.isFile()) {
//           // relativePath = dir.getName();
//            addEntry("download", null, scatterSample);
//            return;
//        }


//        // 空文件夹
//        if (dir.listFiles().length == 0) {
//            relativePath = dir.getAbsolutePath().replace(scatterSample.getRootPath(), "");
//            addEntry(relativePath + File.separator, dir, scatterSample);
//            return;
//        }
        for (String file : dir) {
            File f = new File(file);
            if (!f.isDirectory()){
//                addEntry(f.getName(), f, scatterSample);//此种写法是多种文件压缩到一个文件夹中
//                relativePath = f.getParent().replace(scatterSample.getRootPaths(), "");
                addEntry(relativePath + File.separator + f.getName(), f, scatterSample);//此种写法是压缩包中包括文件夹路径
            }
        }
    }
}

2、将多个文件放在一个文件夹中压缩下载

	//压缩多文件(文件全放入根文件夹)
    public void createZipFile(final List<String> rootPaths, final BufferedOutputStream result) throws Exception {
//        File dstFolder = new File(result.getParent());
//        if (!dstFolder.isDirectory()) {
//            dstFolder.mkdirs();
//        }

        final HighEffiCompressZip scatterSample = new HighEffiCompressZip("zip");
        compressCurrentDirectory(rootPaths, scatterSample);
        final ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(result);
        scatterSample.writeTo(zipArchiveOutputStream);
        zipArchiveOutputStream.close();
    }

3、保留多文件文件夹的树形关系,整体压缩下载

	//压缩多文件,保留文件夹树形关系
    public void createZipFileTree(final List<String> rootPaths, final BufferedOutputStream result) throws Exception {
        final HighEffiCompressZip scatterSample = new HighEffiCompressZip("zip");
        compressCurrentDirectoryTree(rootPaths, scatterSample);
        final ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(result);
        scatterSample.writeTo(zipArchiveOutputStream);
        zipArchiveOutputStream.close();
    }

4、保留子文件夹树形关系,将单个文件夹所有内容压缩下载

	//压缩单个文件夹
    private void createZipFileOneDir(final String rootPath, final BufferedOutputStream result) throws Exception {
//        File dstFolder = new File(result.getParent());
//        if (!dstFolder.isDirectory()) {
//            dstFolder.mkdirs();
//        }
        File rootDir = new File(rootPath);
        final HighEffiCompressZip scatterSample = new HighEffiCompressZip(rootDir.getAbsolutePath());
        compressCurrentDirectoryOneDir(rootDir, scatterSample);
        final ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(result);
        scatterSample.writeTo(zipArchiveOutputStream);
        zipArchiveOutputStream.close();
    }

四、方法测试

1、测试将多个文件放入一个文件夹中压缩下载

	@Test
    public void testSample(HttpServletResponse response) throws Exception {
        SimpleDateFormat f = new SimpleDateFormat("yyyyMMddHHmmss");

        OutputStream os = response.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);

        response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode(f.format(new Date()) + ".zip", "UTF-8"));

        //批量多文件
        long begin = System.currentTimeMillis();
        System.out.println(new Date());
        List<String> urls = new ArrayList<String>();
        urls.add("F:/usr/local/mediaData/data/P001.jpg");
        urls.add("F:/usr/local/mediaData/data/P002.jpg");
        urls.add("F:/usr/local/mediaData/data/11/1.txt");
        createZipFile(urls, bos);
        long end = System.currentTimeMillis();
        System.out.println("用时:" + (end - begin) + " ms");
        System.out.println(new Date());
    }

2、测试保留多文件文件夹树形关系,整体压缩下载

	@Test
    public void testSampleTwo(HttpServletResponse response) throws Exception {
        SimpleDateFormat f = new SimpleDateFormat("yyyyMMddHHmmss");

        OutputStream os = response.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);

        response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode(f.format(new Date()) + ".zip", "UTF-8"));

        //批量多文件
        long begin = System.currentTimeMillis();
        System.out.println(new Date());
        List<String> urls = new ArrayList<String>();
        urls.add("F:/usr/local/mediaData/data/P001.jpg");
        urls.add("F:/usr/local/mediaData/data/P002.jpg");
        urls.add("F:/usr/local/mediaData/data/11/1.txt");
        createZipFileTree(urls, bos);
        long end = System.currentTimeMillis();
        System.out.println("用时:" + (end - begin) + " ms");
        System.out.println(new Date());
    }

3、测试保留子文件夹树形关系

	@Test
    public void testSampleThree(HttpServletResponse response) throws Exception {
        SimpleDateFormat f = new SimpleDateFormat("yyyyMMddHHmmss");

        OutputStream os = response.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);

        response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode(f.format(new Date()) + ".zip", "UTF-8"));

        //批量整个文件夹
        long begin = System.currentTimeMillis();
//        final File result = new File("F:/text1.zip");
//        OutputStream os = response.getOutputStream();
//        BufferedOutputStream bos = new BufferedOutputStream(os);
        createZipFileOneDir("F:/usr/local/mediaData/data", bos);
        long end = System.currentTimeMillis();
        System.out.println("用时:" + (end - begin) + " ms");

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值