Java | ZIP打包下载文件


具体代码

实体类:

import com.baomidou.mybatisplus.annotation.*;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;
import java.time.LocalDateTime;

@Data
@TableName("lpn_photo")
@ApiModel
public class LpnPhotoEntity implements Serializable {
	private static final long serialVersionUID = 1L;


	/**
	 * 主键ID
	 */
	@TableId(value = "id", type = IdType.AUTO)
	@ApiModelProperty("主键ID")
	@TableField("id")
	private Integer id;

	/**
	 * 仓库编码
	 */
	@ApiModelProperty("仓库编码")
	@TableField("warehouse_code")
	private String warehouseCode;

	/**
	 * 入仓预报id
	 */
	@ApiModelProperty("入仓预报id")
	@TableField("warehousing_notify_id")
	private Integer warehousingNotifyId;

	/**
	 * 柜号/集装箱编码
	 */
	@ApiModelProperty("柜号/集装箱编码")
	@TableField("container_no")
	private String containerNo;

	/**
	 * LPN
	 */
	@ApiModelProperty("LPN")
	@TableField("lpn")
	private String lpn;

	/**
	 * SKU长度照片
	 */
	@ApiModelProperty("SKU长度照片")
	@TableField("photo1")
	private String photo1;

	/**
	 * SKU宽度照片
	 */
	@ApiModelProperty("SKU宽度照片")
	@TableField("photo2")
	private String photo2;

	/**
	 * SKU高度照片
	 */
	@ApiModelProperty("SKU高度照片")
	@TableField("photo3")
	private String photo3;

	/**
	 * SKU重量照片
	 */
	@ApiModelProperty("SKU重量照片")
	@TableField("photo4")
	private String photo4;

	/**
	 * 创建时间
	 */
	@ApiModelProperty("创建时间")
	@TableField(value = "created_datetime", fill = FieldFill.INSERT)
	private LocalDateTime createdDatetime;

	/**
	 * 更新时间
	 */
	@ApiModelProperty("更新时间")
	@TableField(value = "updated_datetime", fill = FieldFill.INSERT_UPDATE)
	private LocalDateTime updatedDatetime;

}


工具类:

import com.opene.config.exception.ResultException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Component
@Slf4j
public class ZipUtil {

    public static void zip(ZipOutputStream zipOutputStream, String fileName, byte[] bytes) {
        try {
            ZipEntry zipEntry = new ZipEntry(fileName);
            zipOutputStream.putNextEntry(zipEntry);
            zipOutputStream.write(bytes);
        } catch (Exception e) {
            log.info("抛出异常后跳过,继续向下执行");
        }
    }

    public static ZipOutputStream getZipOutputStream(HttpServletResponse response, String fileName) {
        try {
            ZipOutputStream zipOutputStream = null;
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".zip");
            zipOutputStream = new ZipOutputStream(response.getOutputStream());
            return zipOutputStream;
        } catch (Exception e) {
            throw new ResultException("获取ZipOutputStream异常");
        }
    }
}


使用类案例:

Controller

@PostMapping("/downloadImages")
@ApiOperation("下载图片")
public void download(@Validated @RequestBody TallyLpnDownLoadReqVo vo, HttpServletResponse response) throws IOException {
    tallyService.tallyLpnPhotoDownload(vo.getLpnPhotoIds(), response);
}

Service

void tallyLpnPhotoDownload(List<Integer> lpnPhotoIds, HttpServletResponse response);

ServiceImpl:

@Override
public void tallyLpnPhotoDownload(List<Integer> lpnPhotoIds, HttpServletResponse response) {
    List<LpnPhotoEntity> list = lpnPhotoService.queryByIds(lpnPhotoIds);
    if (CollectionUtils.isEmpty(list)) {
        throw new ResultException("No images to download");
    }

    Map<String, List<LpnPhotoEntity>> collect = list.stream().collect(Collectors.groupingBy(LpnPhotoEntity::getContainerNo));

    ZipOutputStream zipOutputStream = null;
    try {
        // 最外层的ZIP名称
        String filename = URLEncoder.encode("tally_lpn", "UTF-8");
        zipOutputStream = ZipUtil.getZipOutputStream(response, filename);
        List<CompletableFuture<Map<String, byte[]>>> futures = new ArrayList<>();
        collect.forEach((k, v) -> {
            CompletableFuture<Map<String, byte[]>> overallFuture = CompletableFuture.supplyAsync(() -> {
                Map<String, byte[]> map = new HashMap<>();
                // ZIP包第一层的文件夹名称
                String path = String.format("%s/", k);
                for (LpnPhotoEntity lpnPhoto : v) {
                    if (StringUtils.isNotBlank(lpnPhoto.getPhoto1())) {
                        String photo1 = lpnPhoto.getPhoto1();
                        String suffix = photo1.substring(photo1.lastIndexOf("."));
                        // 这里设置LPN为第二层文件夹,如果第二层文件夹一致,则会自动归类
                        String pathName = String.format("%s%s/photo1%s", path, lpnPhoto.getLpn(), suffix);
                        byte[] bytes = gcloudStorageUtil.publicGetBytes(photo1, Constant.wms);
                        map.put(pathName, bytes);
                    }
                    if (StringUtils.isNotBlank(lpnPhoto.getPhoto2())) {
                        String photo2 = lpnPhoto.getPhoto2();
                        String suffix = photo2.substring(photo2.lastIndexOf("."));
                        String pathName = String.format("%s%s/photo2%s", path, lpnPhoto.getLpn(), suffix);
                        byte[] bytes = gcloudStorageUtil.publicGetBytes(photo2, Constant.wms);
                        map.put(pathName, bytes);
                    }
                    if (StringUtils.isNotBlank(lpnPhoto.getPhoto3())) {
                        String photo3 = lpnPhoto.getPhoto3();
                        String suffix = photo3.substring(photo3.lastIndexOf("."));
                        String pathName = String.format("%s%s/photo3%s", path, lpnPhoto.getLpn(), suffix);
                        byte[] bytes = gcloudStorageUtil.publicGetBytes(photo3, Constant.wms);
                        map.put(pathName, bytes);
                    }
                    if (StringUtils.isNotBlank(lpnPhoto.getPhoto4())) {
                        String photo4 = lpnPhoto.getPhoto4();
                        String suffix = photo4.substring(photo4.lastIndexOf("."));
                        String pathName = String.format("%s%s/photo4%s", path, lpnPhoto.getLpn(), suffix);
                        byte[] bytes = gcloudStorageUtil.publicGetBytes(photo4, Constant.wms);
                        map.put(pathName, bytes);
                    }
                }
                return map;
            }, asyncServiceExecutor);
            futures.add(overallFuture);
        });
        if (CollectionUtils.isEmpty(futures)) {
            return;
        }
        for (CompletableFuture<Map<String, byte[]>> future : futures) {
            Map<String, byte[]> map = future.get();
            for (Map.Entry<String, byte[]> m : map.entrySet()) {
                ZipUtil.zip(zipOutputStream, m.getKey(), m.getValue());
            }
        }

        zipOutputStream.flush();
        zipOutputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (Objects.nonNull(zipOutputStream)) {
            try {
                zipOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

ZIP文件层级图

zip包

在这里插入图片描述


第一层文件夹

在这里插入图片描述


第二层文件夹

在这里插入图片描述


第三层的文件

在这里插入图片描述


欢迎关注公众号:慌途L
后面会慢慢将文章迁移至公众号,也是方便在没有电脑的情况下可以进行翻阅,更新的话会两边同时更新,大家不用担心!
在这里插入图片描述


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值