Java 批量压缩打包下载文件


前言

Java 批量压缩打包下载文件,文件为图片时可同时设置水映效果。


tips: ZipOutputStream;DataOutputStream

一、压缩打包

1.获取浏览器信息

	  // 返回客户端浏览器的版本号、类型
      String agent = request.getHeader("USER-AGENT");
      try {
          // 针对IE或者以IE为内核的浏览器:
          if (agent.contains("MSIE") || agent.contains("Trident")) {
              downloadName = java.net.URLEncoder.encode(downloadName, "UTF-8");
          } else {
              // 非IE浏览器的处理:
              downloadName = new String(downloadName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
          }
      } catch (Exception e) {
          log.error("获取浏览器信息异常:异常原因: {}",e.getMessage());
      }

2.压缩打包

public static <T extends BaseEntity> void qualificationsDownloadFile(List<Attachment> list, HttpServletRequest request, HttpServletResponse response) {
        // 设置响应头信息
        response.reset();
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        // 设置压缩包的名字,date为时间戳
        String date = formatDateTimeSecond(new Date());
        String downloadName = "···";
        response.setHeader("Content-Disposition", "attachment;fileName=\"" + downloadName + "\"");
        // 设置压缩流:直接写入response,实现边压缩边下载
        ZipOutputStream zipOs = null;
        // 循环将文件写入压缩流
        DataOutputStream os = null;
        File file;
        try {
            zipOs = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
            // 设置压缩方法
            zipOs.setMethod(ZipOutputStream.DEFLATED);
            // 遍历文件信息(主要获取文件名/文件路径等)
            if(CollectionUtil.isNotEmpty(list)){
                Map<String, String> convert = convert(zipName);
                for (Attachment it : list) {
                    try {
                        // 文件名(包含后缀名,如:测试.jpg)
                        Field fileName = it.getClass().getDeclaredField("name");
                        fileName.setAccessible(true);
                        String name = it.getName();
                        // 本地文件路径(绝对路径,包含后缀名,如:F:\\test\\测试.jpg),这里是在windows上测试的,路径是反斜杠
                        Field filePath = it.getClass().getDeclaredField("location");
                        filePath.setAccessible(true);
                        String path = it.getLocation();
                        // 解决中文名称乱码问题
                        HttpHeaders headers = new HttpHeaders();
                        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
                        headers.setContentDispositionFormData("name", name);
                        // 设置水印
                        // String path = Location.substring(0, index) + "/"  + "-" + annexOtherName;
                        // String outPath = Watermarking.waterToImage(Location, path, Color.DARK_GRAY, convert.get("start"), convert.get("end"));
						// 需要水印则 : path  =  outImgPath 
                        log.info("batchDownloadFile:[filePath:{}]", path);
                        file = new File(path);
                        if (!file.exists()) {
                            throw new RuntimeException("文件不存在");
                        }
                        //添加ZipEntry,并将ZipEntry写入文件流
                        zipOs.putNextEntry(new ZipEntry(name));
                        os = new DataOutputStream(zipOs);
                        FileInputStream fs = new FileInputStream(file);
                        byte[] b = new byte[1024];
                        int length;
                        //读入需要下载的文件的内容,打包到zip文件
                        while ((length = fs.read(b)) != -1) {
                            os.write(b, 0, length);
                        }
                        //关闭流
                        fs.close();
                        zipOs.closeEntry();
                    } catch (IllegalAccessException | NoSuchFieldException e) {
                        log.error("下载文件出错![{}]", e.getMessage());
                    }
                }
            }
        } catch (Exception e) {
            log.error("外层:下载文件出错![{}]", e.getMessage());
        } finally {
            //关闭流
            try {
                if (os != null) {
                    os.flush();
                    os.close();
                }
                if (zipOs != null) {
                    zipOs.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }

    }

List list : 文件具体信息,包含文件名,文件路径等


二、水印工具类

代码如下(示例):

    static String watermarkToImage(String srcImgPath, String outImgPath, Color contentColor,
                                          String waterMarkContent, String waterMarkContent2){
        FileOutputStream outImgStream = null;
        try {
            int lengthAll = waterMarkContent.length();
            // 读取原图片信息
            File srcImgFile = new File(srcImgPath);
            Image srcImg = ImageIO.read(srcImgFile);
            int srcImgWidth = srcImg.getWidth(null);
            int srcImgHeight = srcImg.getHeight(null);
            // 加水印
            BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bufImg.createGraphics();
            g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
            Font font = new Font("宋体", Font.BOLD, 30);
            if(lengthAll >= 50){
                font = new Font("宋体", Font.BOLD, 25);
            }
            //根据图片的背景设置水印颜色
            g.setColor(contentColor);
            //设置旋转角度
            g.rotate(Math.toRadians(45), (double) bufImg.getWidth() / 2, (double) bufImg.getHeight() / 2);
            //设置水印透明度
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.2F));
            g.setFont(font);
            int x = (srcImgWidth - getWatermarkLength(waterMarkContent, g)) / 2;
            int y = srcImgHeight / 2;
            g.drawString(waterMarkContent, x, y);
            g.drawString(waterMarkContent2, x + getWatermarkLength(waterMarkContent, g) - getWatermarkLength(waterMarkContent2, g), y + 50);
            g.dispose();
            // 输出图片
            outImgStream = new FileOutputStream(outImgPath);
            if(srcImgPath.endsWith(".png")){
                ImageIO.write(bufImg, "png", outImgStream);
            } else {
                ImageIO.write(bufImg, "jpg", outImgStream);
            }
            outImgStream.flush();
        } catch (Exception e){
            log.error("水印输入输出异常,异常原因:{}",e.getMessage());
        }
        return outImgPath;
    }

srcImgPath:输入地址
outImgPath,:输出地址
contentColor: 颜色
waterMarkContent: 第一行水映
waterMarkContent2:第二行水映(可为“”)


三、工具类包

1.压缩打包引入

代码如下(示例):

import org.apache.shiro.SecurityUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

2.水映引入

代码如下(示例):

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值