本篇文章包括以下内容:
- 从本地读取文件添加水印并保存到本地的工具类。
- 改良的使用方法,从minio中读取图片添加水印,并使用文件输入流将文件返回给前端。
- 工具类
package testtttt;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
/** * Description: 图片水印工具类 * @authortengk * @version1.0 */
public class ImgWaterMarkUtil {
// 水印透明度private static float alpha= 0.7f;
// 水印横向位置private static int positionWidth= 150;
// 水印纵向位置private static int positionHeight= 300;
// 水印文字字体private static Font font= new Font("宋体", Font.BOLD, 20);
// 水印文字颜色private static Color color= Color.white;
//文字水印位置铺满全屏private static ArrayList position1;
private static ArrayList position2;
/** * * @paramalpha * 水印透明度 * @parampositionWidth * 水印横向位置 * @parampositionHeight * 水印纵向位置 * @paramfont * 水印文字字体 * @paramcolor * 水印文字颜色 */public static void setImageMarkOptions(float alpha, int positionWidth,
int positionHeight, Font font, Color color) {
if (alpha != 0.0f) {
ImgWaterMarkUtil.alpha = alpha;
}
if (positionWidth != 0) {
ImgWaterMarkUtil.positionWidth = positionWidth;
}
if (positionHeight != 0) {
ImgWaterMarkUtil.positionHeight = positionHeight;
}
if (font != null) {
ImgWaterMarkUtil.font = font;
}
if (color != null) {
ImgWaterMarkUtil.color = color;
}
}
/** * 给图片添加水印图片 * * @paramiconPath * 水印图片路径 * @paramsrcImgPath * 源图片路径 * @paramtargerPath * 目标图片路径 */public static void markImageByIcon(String iconPath, String srcImgPath,
String targerPath) {
markImageByIcon(iconPath, srcImgPath, targerPath, null);
}
/** * 给图片添加水印图片、可设置水印图片旋转角度 * * @paramiconPath * 水印图片路径 * @paramsrcImgPath * 源图片路径 * @paramtargerPath * 目标图片路径 * @paramdegree * 水印图片旋转角度 */public static void markImageByIcon(String iconPath, String srcImgPath,
String targerPath, Integer degree) {
OutputStream os = null;
try {
Image srcImg = ImageIO.read(new File(srcImgPath));
BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null),
srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB);
// 1、得到画笔对象Graphics2D g = buffImg.createGraphics();
// 2、设置对线段的锯齿状边缘处理g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(
srcImg.getScaledInstance(srcImg.getWidth(null),
srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0,
null);
// 3、设置水印旋转if (null != degree) {
g.rotate(Math.toRadians(degree),
(double) buffImg.getWidth() / 2,
(double) buffImg.getHeight() / 2);
}
// 4、水印图片的路径 水印图片一般为gif或者png的,这样可设置透明度ImageIcon imgIcon = new ImageIcon(iconPath);
// 5、得到Image对象。Image img = imgIcon.getImage();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
alpha));
// 6、水印图片的位置g.drawImage(img, positionWidth, positionHeight, null);
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
// 7、释放资源g.dispose();
// 8、生成图片os = new FileOutputStream(targerPath);
ImageIO.write(buffImg, "JPG", os);
System.out.println("图片完成添加水印图片");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(null != os) {
os.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/** * 给图片添加水印文字 * * @paramlogoText * 水印文字 * @paramsrcImgPath * 源图片路径 * @paramtargerPath * 目标图片路径 */public static void markImageByText(String logoText, String srcImgPath,
String targerPath,int allFlag) {
markImageByText(logoText, srcImgPath, targerPath, null,allFlag);
}
/** * 给图片添加水印文字、可设置水印文字的旋转角度 * * @paramlogoText * @paramsrcImgPath * @paramtargerPath * @paramdegree */public static void markImageByText(String logoText, String srcImgPath,
String targerPath, Integer degree,int allFlag) {
InputStream is = null;
OutputStream os = null;
try {
// 1、源图片Image srcImg = ImageIO.read(new File(srcImgPath));
BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null),
srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB);
// 2、得到画笔对象Graphics2D g = buffImg.createGraphics();
// 3、设置对线段的锯齿状边缘处理g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(
srcImg.getScaledInstance(srcImg.getWidth(null),
srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0,
null);
// 4、设置水印旋转if (null != degree) {
g.rotate(Math.toRadians(degree),
(double) buffImg.getWidth() / 2,
(double) buffImg.getHeight() / 2);
}
// 5、设置水印文字颜色g.setColor(color);
// 6、设置水印文字Fontg.setFont(font);
// 7、设置水印文字透明度g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
alpha));
// 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y)if (allFlag == 1){
int width = srcImg.getWidth(null);
int height = srcImg.getHeight(null);
position1 = new ArrayList();
position2 = new ArrayList();
position1.add(0);
position1.add(width/4);
position1.add(width/2);
position1.add(width*3/4);
position1.add(width);
position2.add(0);
position2.add(height/4);
position2.add(height/2);
position2.add(height*3/4);
position2.add(height);
for (int i = 0; i < position1.size(); i++) {
for (int j = 0; j < position2.size(); j++) {
g.drawString(logoText,(Integer) position1.get(i),(Integer) position2.get(j));
}
}
}else {
g.drawString(logoText,positionWidth,positionHeight);
}
// 9、释放资源g.dispose();
// 10、生成图片os = new FileOutputStream(targerPath);
ImageIO.write(buffImg, "JPG", os);
System.out.println("图片完成添加水印文字");
} catch (Exception e) {
System.out.println("图片加水印失败");
throw new RuntimeException("图片加水印失败");
} finally {
try {
if (null == is) {
} else {
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (null != os) {
os.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
String markText = "cq-tengk "+new SimpleDateFormat("yyyy-MM-dd").format(new Date());
//图片测试String srcImgPath = "E:/ylnew/111.jpg";
String targerTextPath2 = "E:/ylnew/3000.jpg";
String targerTextPath = "E:/ylnew/3001.jpg";
// 给图片添加水印文字markImageByText(markText, srcImgPath, targerTextPath,0);
// 给图片添加水印文字,水印文字旋转-45markImageByText(markText, srcImgPath, targerTextPath2, -45,1);
//文件测试// String oldFile = "D:/tmp/tmp/20A00053公开招标(定稿).doc";// String newFile = "D:/tmp/res/20A00053公开招标(定稿).doc";// String oldFile = "D:/tmp/tmp/5G专网产品资费设计.docx";// String newFile = "D:/tmp/res/5G专网产品资费设计.docx";// String oldFile = "D:/tmp/tmp/2.xlsx";// String newFile = "D:/tmp/res/22.xlsx";String oldFile = "D:/tmp/tmp/2.pdf";
String newFile = "D:/tmp/res/22.pdf";
// String oldFile = "D:/tmp/tmp/2.pptx";// String newFile = "D:/tmp/res/2.pptx";// OfficeWaterMarkUtil.addWaterMarkOffice(oldFile,newFile,markText);}
}
- service层使用示例,以文件流形式返回
// 图片水印方法@Override
public void getWatermarkedFile(String sourceObjectPath, HttpServletResponse response) {
System.out.println("sourceObjectPath: " + sourceObjectPath);
// 检查源桶中的文件是否存在boolean objectExists = false;
try {
minioClient.statObject(
StatObjectArgs.builder()
.bucket(minIOWatermarkConfig.getBucketName())
.object(sourceObjectPath)
.build()
);
objectExists = true; // 如果没有抛出异常,则对象存在} catch (ErrorResponseException e) {
if ("NoSuchKey".equals(e.errorResponse().code())) {
System.err.println("源文件不存在: " + minIOWatermarkConfig.getBucketName() + "/" + sourceObjectPath);
return; // 结束方法执行,因为源文件不存在} else {
throw new RuntimeException(e);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
// 如果文件存在,执行后续操作if (objectExists) {
try {
// 下载文件到临时文件 图片处理逻辑File tempFile = File.createTempFile("temp", ".tmp");
minioClient.downloadObject(
DownloadObjectArgs.builder()
.bucket(minIOWatermarkConfig.getBucketName())
.object(sourceObjectPath)
.filename(tempFile.getAbsolutePath())
.build()
);
// 添加水印String markText = ImgWaterMarkUtil.markText;
String targetWatermarkedFilePath = tempFile.getAbsolutePath() + "_watermarked";
if (sourceObjectPath.endsWith(".png") || sourceObjectPath.endsWith(".jpg")){
ImgWaterMarkUtil.markImageByText(markText, tempFile.getAbsolutePath(), targetWatermarkedFilePath, -45, 1);
}else {
log.error("文件类型暂不支持添加水印");
return;
}
// 设置响应头信息String contentType = "application/octet-stream"; // 默认为二进制流,适用于未知的文件类型String fileName = sourceObjectPath;
String lowerCaseFileName = fileName.toLowerCase();
if (lowerCaseFileName.endsWith(".png")) {
contentType = "image/png"; // PNG 图片} else if (lowerCaseFileName.endsWith(".jpg") || lowerCaseFileName.endsWith(".jpeg")) {
contentType = "image/jpeg"; // JPG 图片// } else if (lowerCaseFileName.endsWith(".gif")) {// contentType = "image/gif"; // GIF 图片}
response.setContentType(contentType);
response.setHeader("Content-Disposition", "attachment; filename=\"" + tempFile.getName() + "\"");
// response.setHeader("Content-Disposition", "inline; filename=\"" + tempFile.getName() + "\""); attachment 下载 inline显示// 通过临时文件路径获取加水印后的文件File watermarkedFile = new File(targetWatermarkedFilePath);
System.out.println(fileName);
// 使用文件输入流读取文件返回到服务端try (InputStream inputStream = new FileInputStream(watermarkedFile);
OutputStream outputStream = response.getOutputStream()) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
}
// 删除临时文件tempFile.delete();
new File(targetWatermarkedFilePath).delete();
} catch (Exception e) {
// 异常处理log.error("Error processing file", e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}