场景
一个图片文件查看或者下载前需要加上水印,文件本身存储在共享文件夹下。
共享文件(Smb共享)
mac下共享文件
操作步骤:
- 系统偏好设置-共享-文件共享-使用smb共享文件或文件夹,访问用户为guset,密码为空
- 系统偏好设置-用户和群组-解锁-客人用户-允许客人登录到这台电脑
linux下共享文件
操作步骤:安装smb-创建文件夹-修改smb配置文件-重启smb服务即可
Windows下共享文件
操作步骤:创建文件夹-右键设置共享目录-共享用户添加
详细 请移步百度搜索…
操作共享文件
Maven依赖
<dependency>
<groupId>jcifs</groupId>
<artifactId>jcifs</artifactId>
<version>1.3.17</version>
</dependency>
共享文件操作
使用SmbFile类
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", "guest", "");
SmbFile smbFile = new SmbFile("smb://127.0.0.1/shareDir/1.jpg", auth);
图片文件加水印
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbException;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileOutputStream;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.net.MalformedURLException;
/**
* 远程图片添加水印工具类
*/
@Slf4j
public final class FileWatermarkUtils {
private static final String IMG_FILE_NAME_SEPARATOR = ".";
/**
* 水印文字字体名
*/
private static final String FONT_NAME = "华文楷体";
/**
* 水印文字样式
*/
private static final int FONT_STYLE = Font.BOLD;
/**
* 水印文字颜色
*/
private static final Color FONT_COLOR = Color.BLACK;
/**
* 水印文字字体大小
*/
private static final int FONT_SIZE = 20;
/**
* 透明度
*/
private static final float ALPHA = 0.1f;
/**
* 水印旋转角度
*/
private static final int DEGREE = -30;
/**
* 各个水印文字间隔像素-X 根据图片大小 可自行调整
*/
private static final int OFFSET_GAP_X = 200;
/**
* 各个水印文字间隔像素-Y 根据图片大小 可自行调整
*/
private static final int OFFSET_GAP_Y = 100;
private FileWatermarkUtils() {}
/**
* 读取smbFile图片文件 添加水印后 生成到newSmbFile
* @param smbFile 原远程图片文件
* @param newSmbFile 新的添加水印后的文件
* @param watermarkText 添加的水印
*/
public static void addWatermarkToNewSmbFile(SmbFile smbFile, SmbFile newSmbFile, String watermarkText) {
try (InputStream smbFileInputStream = smbFile.getInputStream(); SmbFileOutputStream newSmbFileOutputStream = (SmbFileOutputStream) newSmbFile.getOutputStream()) {
log.info("Start to add watermark to image file.");
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 1、读取输入流,构建Image对象
Image src = ImageIO.read(smbFileInputStream);
log.info("Read file end, cost {}", stopWatch.getTime());
int width = src.getWidth(null);
int height = src.getHeight(null);
log.info("Get image width and height end, cost {}", stopWatch.getTime());
// 2、构建Graphics2D
BufferedImage bufferedImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = bufferedImage.createGraphics();
graphics2D.drawImage(src, 0, 0, width, height, null);
// 设置字体与颜色
Font font = new Font(FONT_NAME, FONT_STYLE, FONT_SIZE);
graphics2D.setColor(FONT_COLOR);
graphics2D.setFont(font);
// 设置透明度
graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));
log.info("Prepare to draw image end, cost {}", stopWatch.getTime());
// 3、获取要添加的水印文字所占的像素
FontRenderContext context = graphics2D.getFontRenderContext();
Rectangle2D stringBounds = font.getStringBounds(watermarkText, context);
log.info("Get string bounds end, cost {}", stopWatch.getTime());
// 4、绘制水印
int textWidthHalf = ((int) stringBounds.getWidth()) >>> 1;
int textHeightHalf = ((int) stringBounds.getHeight()) >>> 1;
AffineTransform old = graphics2D.getTransform();
int positionX = 0;
int positionY = 0;
while (positionX <= width) {
while (positionY <= height) {
// 以当前要绘制的文字的中心点为中心进行旋转
graphics2D.rotate(Math.toRadians(DEGREE), positionX + textWidthHalf, positionY + textHeightHalf);
// 绘制水印
graphics2D.drawString(watermarkText, positionX, positionY);
// 重置transform
graphics2D.setTransform(old);
positionY += OFFSET_GAP_Y;
}
positionY = 0;
positionX += OFFSET_GAP_X;
}
log.info("Draw watermark text end, cost {}", stopWatch.getTime());
// 销毁绘制使用的资源
graphics2D.dispose();
// 5、添加完水印的文件写到新的远程文件中
// 获取文件后缀
String filePath = newSmbFile.getPath();
String fileSuffix = filePath.substring(filePath.lastIndexOf(IMG_FILE_NAME_SEPARATOR) + 1);
// 图片缓存写入新文件
ImageIO.write(bufferedImage, fileSuffix, newSmbFileOutputStream);
log.info("Save image with watermark to new smb file, cost {}", stopWatch.getTime());
stopWatch.stop();
} catch (Exception ex) {
log.error("FileWatermarkUtils-addWatermarkToSmbFile: add watermark to smb file exception.", ex);
}
}
public static void main(String [] args) throws MalformedURLException, SmbException {
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", "guest", "");
SmbFile smbImageFile = new SmbFile("smb://127.0.0.1/shareDir/1.jpg", auth);
SmbFile newTempImageFileWithWatermark = new SmbFile("smb://127.0.0.1/shareDir/1_temp.jpg", auth);
addWatermarkToNewSmbFile(smbImageFile, newTempImageFileWithWatermark, "one piece");
// newTempImageFileWithWatermark.delete();
}
}
水印图片效果:
遇到的问题
生成的图片无法打开
解决:
权限问题,右键图片-显示简介,解锁图片,添加上当前用户的读写权限即可
访问文件时报错
如账号密码错误,文件找不到,没有权限等
jcifs.smb.SmbAuthException: Logon failure: unknown user name or bad password
jcifs.smb.SmbException: The system cannot find the file specified
解决:
仔细检查当前使用的访问用户是否有共享文件夹的读写权限,文件名,文件路径是否正确。可以在windows机器上访问试下,如果能正常访问,程序应该也是可以访问到的。