基于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();
}
}