前言
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;