基於thumbnailator 實現圖片的水印添加和大小壓縮
通過相關代碼,來改變圖片大小並打上水印。
一、引入Maven依賴
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
二、將我們要對圖片進行的處理,封裝成工具類
import java.io.File;
import net.coobird.thumbnailator.Thumbnails;
public class ImageUtil{
public static void main(String[] args) throws Exception{
//水印圖片的絕對路徑
String basePath = Thread.currentThread().
getContextClassLoader().getResource("").getPath();
//壓縮圖片 並輸出到同級目錄下
Thumbnails.of(new File("Users/baidu/work/image/xiaohuangren.jpg"))
.size(200,200)
.watermark(Positions.BOTTOM_RIGHT,ImageIO
.read(new File(basePath+"/watermark.jpg")),0.25f)
.outputQuality(0.8f)
.toFile("Users/baidu/work/image/xiaohuangren_new.jpg");
}
}
由於圖片處理過程中涉及到File,File又無法避免路徑的獲得,於是,我們可以再創建一個工具類來專門生成路徑地址
public class PathUtil{
private static String seperator =
System.getProperty("file.seperator");
//返回項目圖片的根路徑
public static String getImgBasePath(){
String os = System.getProperty("os.name");
String basePath = "";
if(os.toLowerCase().startsWith("win")){
basePath = "D:/projectdev/image/";
} else{
basePath = "/home/image/";
}
//根據系統的不同 切換不同的 分隔符
basePath = basePath.replace("/",seperator);
return basePath;
}
//返回項目圖片的子路徑
public static String getShopImagePath(long shopId){
String imagePath = "/upload/item/shop/" + shopId + "/";
return imagePath.replace("/",seperator);
}
}
如果在工程中設置了classpath,一旦工程進行移動,那麼圖片將不會跟着移動。
現在很多公司,是直接將圖片保存在另一臺服務器上,利用URL引入進來。
如果只有一臺服務器,那麼保存在另外一個路徑下是比較合理的。
三、正式書寫ImageUtil
public class ImageUtil{
//水印圖片的絕對路徑
private static String basePath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
//隨機對象
private static final Random r = new Random();
// 添加日誌信息 --> new 一個日誌對象
private static Logger logger = LoggerFactory.getLogger(ImageUtil.class);
//處理縮略圖,並返回新生成圖片的相對值路徑
//spring會將前端傳遞來的圖片,用 MultipartFile接口 的實現類CommonsMulitipartFile來處理
/*
tansferTo 將FileItem 類型 轉成 java.io.File 類型 只能是單向的
爲了方便service層的UT測試,可以將CommonsMulitipartFile 類型暫時更改爲java.io.File類型
因爲File類型是沒有辦法變成CommonsMulitipartFile類型的。CommonsMulitipartFile初始化的時候
傳入的是一個 FileItem類型 的對象,而不是java.io.File
*/
//將CommonsMultipartFile 轉換成 File
public static File transferCommonsMultipartFileToFile(CommonsMultipartFile cFile){
File newFile = new File(cFile.getOriginalFilename());
try{
cFile.transferTo(newFile);
}catch(IllegalStateException e){
logger.error(e.toString());
e.printStackTrace();
}catch(IOException e){
logger.error(e.toString());
e.printStachTrace();
}
return newFile();
}
public static String generateThumbnail(CommonsMultipartFile thumbnail, String targetAddr){
//隨機生成不重複的文件名用於保存
String realFileName = getRandomFileName();
//拿到文件的拓展名
String extension = getFileExtension(thumbnail);
//有可能保存的目的地並不存在,我們就給創建出來
makeDirPath(targetAddr);
String relativeAddr = targetAddr + realFileName + extension;
logger.debug("current relativeAddr is : " + relativeAddr);
File dest = new File(PathUtil.getImgBasePath() + relativeAddr);
logger.debug("current complate addr is :" + PathUtil.getImgBasePath() + relativeAddr);
try{
Thumbnails.of(thumbnail.getInputStream()).size(200,200)
.watermark(Positions.BOTTOM_RIGHT,ImageIO.read(new File(basePath+"/watermark.jpg")),0.25f)
.outputQuality(0.8f)
.toFile(dest);
}catch(Exception e){
logger.error(e.toString());
e.printStackTrace();
}
//返回相對路徑地址 存入數據庫 通過getBasePath動態獲取根路徑,
//以保障無論項目遷移到哪裏,我們都可以照常獲取
return relativeAddr;
}
//生成隨機文件名,當前年月日小時分鐘秒鐘+五位隨機數
private static String getRandomFileName(){
//獲取隨機的五位數
//r.nextInt() 從0到指定的數 之間的一個隨機數
int randnum = r.nextInt(89999)+10000;
String nowTimeStr = sDateFomat.format(new Date());
return nowTimeStr + randnum;
}
//獲得輸入文件流的擴展名 獲取最後一個點 之後的內容即可
private static String getFileExtension(CommonsMutipartFile cFile){
String originalFileName = cFile.getOriginalFileName();
return originalFileName.substring(originalFileName.lastIndexOf("."));
}
//創建目標路徑所涉及到的目錄,即/home/work/xxx.jpg ,
//那麼home/work兩個文件夾需要自動創建
private static void makeDirPath(String targetAddr){
//targetAddr 是相對路徑,我們需要獲取它的絕對路徑
String realFileParentPath = PathUtil.getImgBasePath() + targetAddr;
File dirPath = new File(realFileParentPath);
if(!dirPath.exists()){
//從頭挨着創建
dirPath.mkdirs();
}
}