Springboot将多个图片导出成zip压缩包

Springboot将多个图片导出成zip压缩包

将多个图片导出成zip压缩包

/**
     * 判断时间差是否超过6小时
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return
     */
    public static boolean isWithin6Hours(String startTime, String endTime) {
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 将字符串转换为 LocalDateTime
        LocalDateTime startDateTime = LocalDateTime.parse(startTime,formatter);
        LocalDateTime endDateTime = LocalDateTime.parse(endTime,formatter);

        // 检查两个时间之间的时间差
        long hoursDifference = ChronoUnit.SECONDS.between(startDateTime, endDateTime);

        // 如果小时差小于等于6小时,则符合条件
        return hoursDifference <= 6 * 60 * 60;
    }

    /**
     * 批量下载上传的图片
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     */
    public void batchDownloadUploadPhoto(String startTime, String endTime,String fieldId,String unitTypeId,Integer unitNo,Integer termAddr, HttpServletResponse response, HttpServletRequest request) {

        if (StringUtils.isEmpty(startTime) || StringUtils.isEmpty(endTime)) {
            throw new DataValidateErrorException("请先传递时间在批量导出!");
        }

        if (!startTime.contains(":") || !endTime.contains(":")) {
            throw new DataValidateErrorException("请传递时分秒");
        }

        //相隔时间不得超过6小时
        if(!isWithin6Hours(startTime,endTime)){
            //大于6小时,抛出异常
            throw new DataValidateErrorException("导出的时间范围不得超过6小时!");
        }


        //查询导出图片url
        List<ChuteImageAddress> addressList = chuteImageAddressService.selectUploadPhoto(startTime, endTime, fieldId, unitTypeId, unitNo, termAddr);

        //没有数据时,抛出异常
        if(CollectionUtils.isEmpty(addressList)){
            throw new DataValidateErrorException("无数据导出!");
        }


        DownloadByteArray downloadByteArray = new DownloadByteArray();

        // 创建临时文件
        File zipFile = null;
        FileInputStream fis = null;
        BufferedInputStream buff = null;
        ZipOutputStream zos = null;
        CheckedOutputStream cos = null;
        FileOutputStream fot = null;
        ServletOutputStream os = null;
        try {
            //临时文件名称
            zipFile = File.createTempFile("" + System.currentTimeMillis(), ".zip");

            fot = new FileOutputStream(zipFile);
            // 为任何OutputStream产生校验,第一个参数是制定产生校验和的输出流,第二个参数是指定Checksum的类型 (Adler32(较快)和CRC32两种)

            cos = new CheckedOutputStream(fot, new Adler32());
            // 用于将数据压缩成Zip文件格式

            zos = new ZipOutputStream(cos);

            String[] files = new String[addressList.size()];
            List<String> list = addressList.stream().map(ChuteImageAddress::getImgUrl).collect(Collectors.toList());
            list.toArray(files);

            for (int i = 0; i < files.length; i++) {
                String file = files[i];
                zos.putNextEntry(new ZipEntry(addressList.get(i).getImgName()));
                StorePath storePath = StorePath.praseFromUrl(file);
                byte[] fileBytes = client.downloadFile(storePath.getGroup(), storePath.getPath(), downloadByteArray);
                zos.write(fileBytes);
            }

            os = response.getOutputStream();
            //下载文件,使用spring框架中的FileCopyUtils工具
            response.setCharacterEncoding("GB2312");
            response.setContentType(request.getSession().getServletContext().getMimeType(UUIDUtil.create()));
            //设置响应头,attachment表示以附件的形式下载,inline表示在线打开
            response.setHeader("content-disposition", "attachment;fileName=" + URLEncoder.encode("批量下载.zip", "UTF-8"));
            fis = new FileInputStream(zipFile);
            buff = new BufferedInputStream(fis);
            FileCopyUtils.copy(buff, os);
        } catch (Exception e) {
            log.error("【批量下载图片出现异常】异常原因" + e.getMessage());
        } finally {
            if (zos != null) {
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (fot != null) {
                try {
                    fot.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (buff != null) {
                try {
                    buff.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }
    }

在这里插入图片描述
在这里插入图片描述

Spring Boot应用程序在将多个文件压缩为ZIP文件时遇到内存溢出问题,通常是因为尝试一次性将大量文件加载到内存中,从而导致堆内存溢出。为了解决这个问题,可以采取以下措施: 1. 使用流式处理(streaming)方法来创建ZIP文件,这样就不需要一次性将所有文件加载到内存中。 2. 分批次处理文件,每次只处理一部分文件,然后再逐步添加到ZIP文件中。 3. 确保JVM的堆内存足够大,可以处理当前的文件集合大小,但这并不是最佳解决方案,因为它不能从根本上解决问题。 下面是一个使用Java的`ZipOutputStream`类来分批处理文件并创建ZIP文件的代码示例。此示例不会一次性加载所有文件到内存,而是逐步写入ZIP流中: ```java import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @RestController public class FileExportController { @GetMapping("/export") public ResponseEntity<byte[]> exportFiles() throws IOException { HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition", "attachment; filename=\"files.zip\""); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream); // 假设有一个文件列表,实际使用时应该是从文件系统中获取 String[] filePaths = { "path/to/your/file1.txt", "path/to/your/file2.txt", ... }; for (String filePath : filePaths) { Path path = Paths.get(filePath); // 创建新的ZIP条目 zipOutputStream.putNextEntry(new ZipEntry(path.getFileName().toString())); // 读取文件内容并写入ZIP条目 Files.copy(path, zipOutputStream); zipOutputStream.closeEntry(); } zipOutputStream.finish(); zipOutputStream.close(); return ResponseEntity.ok() .headers(headers) .body(byteArrayOutputStream.toByteArray()); } } ``` 在这个示例中,`ZipOutputStream`用于创建ZIP文件流,然后我们逐个处理每个文件,将其内容写入到ZIP流中,而不是一次性读取所有文件到内存中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兴奋の大公猴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值