Java实现多个文件生成压缩包下载

目录

1、工具类代码

2、FileInfo实体类

3、控制层调用代码


1、工具类代码

package com.shucha.digitalportal.biz.utils;


import com.shucha.digitalportal.biz.model.FileInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;

import java.io.*;
import java.util.List;

import static org.springframework.util.StreamUtils.BUFFER_SIZE;

/**
 * 附件下载  生成压缩包
 */
@Slf4j
public class ZipUtils {

    /**
     * 多个文件压缩下载
     * @param outputStream
     * @param fileList 多个file文件list
     * @throws IOException
     */
    public static void downloadZip(OutputStream outputStream, List<FileInfo> fileList) throws IOException {
        try (ZipOutputStream zos = new ZipOutputStream(outputStream)) {
            zos.setEncoding("GBK");
            for (FileInfo fileInfo : fileList) {
                File file = new File(fileInfo.getFilePath());
                if (file.exists()) {
                    ZipEntry zipEntry = new ZipEntry(fileInfo.getFileName());
                    zos.putNextEntry(zipEntry);
                    byte[] buf = new byte[BUFFER_SIZE];
                    int len;
                    FileInputStream in = new FileInputStream(file);
                    while ((len = in.read(buf)) != -1) {
                        zos.write(buf, 0, len);
                        zos.flush();
                    }
                }
            }
            zos.flush();
        } catch (IOException e) {
            log.error("文件压缩异常:", e);
            throw e;
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                log.error("导出文件关闭流异常", e);
            }
        }
    }

    /**
     * 压缩的文件就是传递过来的文件名称
     * @param outputStream
     * @param fileList
     * @throws IOException
     */
    public static void downloadZipOldName(OutputStream outputStream, List<File> fileList) throws IOException {
        try (ZipOutputStream zos = new ZipOutputStream(outputStream)) {
            zos.setEncoding("GBK");
            for (File file : fileList) {
                if (file.exists()) {
                    ZipEntry zipEntry = new ZipEntry(file.getName());
                    zos.putNextEntry(zipEntry);
                    byte[] buf = new byte[BUFFER_SIZE];
                    int len;
                    FileInputStream in = new FileInputStream(file);
                    while ((len = in.read(buf)) != -1) {
                        zos.write(buf, 0, len);
                        zos.flush();
                    }
                }
            }
            zos.flush();
        } catch (IOException e) {
            log.error("文件压缩异常:", e);
            throw e;
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                log.error("导出文件关闭流异常", e);
            }
        }
    }

    /**
     * 将文件夹及文件夹包含的内容压缩成zip文件
     * (为了解决中文乱码的问题,ZipOutputStream用org.apache.tools.zip.*)
     *
     * @param inputFile 源文件
     * @param delFlag   删除源文件标记
     * @return File 压缩后的文件
     */
    public static File zipCompress(File inputFile, boolean delFlag) throws Exception {
        File zipFile = null;
        //创建zip输出流
        //为了解决中文乱码的问题,ZipOutputStream用org.apache.tools.zip.*
        //不要用 java.util.zip.*
        if (inputFile != null && inputFile.exists()) {
            try {
                String path = inputFile.getCanonicalPath();
                String zipFileName = path + ".zip";
                zipFile = new File(zipFileName);
                if (zipFile.exists()) {
                    zipFile.delete();
                }
                zipFile.createNewFile();//创建文件
                try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))){
                    //解决中文乱码问题,指定编码GBK
                    zos.setEncoding("GBK");
                    //压缩文件或文件夹
                    compressFile(zos, inputFile, inputFile.getName());
                }
            } catch (Exception e) {
                log.error("文件压缩异常:", e);
                throw e;
            } finally {
                if (delFlag) {
                    //递归删除源文件及源文件夹
                    deleteFile(inputFile);
                }
            }
        }
        return zipFile;
    }

    /**
     * 压缩文件或文件夹
     * (ZipEntry 使用org.apache.tools.zip.*,不要用 java.util.zip.*)
     *
     * @param zos        zip输出流
     * @param sourceFile 源文件
     * @param baseName   父路径
     * @throws Exception 异常
     */
    private static void compressFile(ZipOutputStream zos, File sourceFile, String baseName) throws Exception {
        if (!sourceFile.exists()) {
            return;
        }

        //若路径为目录(文件夹)
        if (sourceFile.isDirectory()) {
            //取出文件夹中的文件(或子文件夹)
            File[] fileList = sourceFile.listFiles();
            //若文件夹为空,则创建一个目录进入点
            if (fileList.length == 0) {
                //文件名称后跟File.separator表示这是一个文件夹
                zos.putNextEntry(new ZipEntry(baseName + File.separator));
                //若文件夹非空,则递归调用compressFile,对文件夹中的每个文件或每个文件夹进行压缩
            } else {
                for (int i = 0; i < fileList.length; i++) {
                    compressFile(zos, fileList[i],
                            baseName + File.separator + fileList[i].getName());
                }
            }

            //若为文件,则先创建目录进入点,再将文件写入zip文件中
        } else {
            ZipEntry ze = new ZipEntry(baseName);
            //设置ZipEntry的最后修改时间为源文件的最后修改时间
            ze.setTime(sourceFile.lastModified());
            zos.putNextEntry(ze);

            try (FileInputStream fis = new FileInputStream(sourceFile)) {
                copyStream(fis, zos);
            }
        }
    }

    /**
     * 流拷贝
     *
     * @param in  输入流
     * @param out 输出流
     * @throws IOException
     */
    private static void copyStream(InputStream in, OutputStream out) throws IOException {
        int bufferLength = 1024 * 100;
        synchronized (in) {
            synchronized (out) {
                int count = 0;
                byte[] buffer = new byte[bufferLength];
                while ((count = in.read(buffer, 0, bufferLength)) != -1) {
                    out.write(buffer, 0, count);
                }
                out.flush();
            }
        }
    }

    /**
     * 递归删除文件夹中的目录及文件
     *
     * @param sourceFile
     * @throws Exception
     */
    private static void deleteFile(File sourceFile) throws Exception {
        //如果路径为目录
        if (sourceFile.isDirectory()) {
            //取出文件夹中的文件或子文件夹
            File[] fList = sourceFile.listFiles();
            if (fList.length == 0) {
                sourceFile.delete();
            } else {
                for (int i = 0; i < fList.length; i++) {
                    deleteFile(fList[i]);
                }
                sourceFile.delete();
            }
            //如果为文件则直接删除
        } else {
            sourceFile.delete();
        }
    }
}

2、FileInfo实体类

package com.shucha.digitalportal.biz.model;

import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import com.sdy.common.model.BaseModel;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.sdy.common.utils.DateUtil;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * <p>
 * 附件信息
 * </p>
 *
 * @author tqf
 * @since 2021-07-15
 */
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class FileInfo extends BaseModel {
    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @ApiModelProperty(value = "主键")
    @JsonSerialize(using = ToStringSerializer.class)
    @TableId
    private Long id;

    /**
     * 数据主键ID
     */
    @ApiModelProperty(value = "数据主键ID")
    private Long dataId;

    /**
     * 附件名称
     */
    @ApiModelProperty(value = "附件名称")
    private String fileName;

    /**
     * 附件路径
     */
    @ApiModelProperty(value = "附件路径")
    private String filePath;

    /**
     * 附件类型(1-通知公告,2-风险气象台)
     */
    @ApiModelProperty(value = "附件类型(1-通知公告,2-风险气象台)")
    private Integer fileType;

    /**
     * 创建时间
     */
    @ApiModelProperty(value = "创建时间")
    @JsonFormat(pattern = DateUtil.DATETIME_FORMAT)
    private Date createTime;

    /**
     * 更新时间
     */
    @ApiModelProperty(value = "更新时间")
    @JsonFormat(pattern = DateUtil.DATETIME_FORMAT)
    private Date updateTime;

}

3、控制层调用代码

@GetMapping(value = "/downFileZip")
    @ApiOperation(value = "多个附件,打包成zip压缩包下载")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "数据ID", required = true),
            @ApiImplicitParam(name = "fileType", value = "附件类型(1-通知公告)", required = true)
    })
    public void downFileZip(HttpServletResponse response, Long id, Integer fileType) throws Exception {
        Assert.isNull(id,"附件地址ID不能为空");
        Assert.isNull(fileType,"附件类型不能为空");
        OutputStream out = null;
        FileInputStream fis = null;
        //文件名
        String fileName = null;
        // 根据数据ID和附件类型 查询附件数据
        List<FileInfo> list = fileInfoService.list(Wrappers.<FileInfo>lambdaQuery()
                .eq(FileInfo::getDataId, id)
                .eq(FileInfo::getFileType,fileType));
        Assert.isTrue(list.size() ==0,"没有对应的附件可下载!");
        String oldFileName = list.get(0).getFileName();
        int t = oldFileName.lastIndexOf(".");
        fileName = t > 0 ? oldFileName.substring(0, t) : oldFileName;
        try {
            out = response.getOutputStream();
            // 附件文件放入文件list
            List<File> fileList = new ArrayList<>();
            for(int i=0;i<list.size();i++){
                File file = new File(list.get(i).getFilePath());
                fileList.add(i,file);
            }
            // 设置response的Header 防止文件名乱码
            response.addHeader("Content-Disposition",
                    "attachment;filename="
                            + new String((fileName+".zip").getBytes("utf-8"), "ISO-8859-1"));
            response.setContentType("application/force-download");
            ZipUtils.downloadZip(out,list);
            // 下面的方法压缩的文件名称是上传文件生成的文件名称
            // ZipUtils.downloadZipOldName(out,fileList);
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("执行 文件下载downFile 方法失败:" + e.getMessage());
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }
posted @ 2022-08-04 19:11  码奴生来只知道前进~  阅读(84)  评论(0编辑  收藏  举报