場景
一個圖片文件查看或者下載前需要加上水印,文件本身存儲在共享文件夾下。
共享文件(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機器上訪問試下,如果能正常訪問,程序應該也是可以訪問到的。