1.图片处理工具Thumbnails,给图片增加水印
1.1 引入依赖
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
1.2 示例
Thumbnails.of(
new File("D:/eclipse/background.jpg")).size(500,500).watermark(
Positions.BOTTOM_RIGHT, ImageIO.read(new File(basePath +"/logo.jpg")),
0.8f).outputQuality(0.8f).toFile("D:/eclipse/background-1.jpg");
:
size(200,200):图片格式大小。
watermark(Positions.BOTTOM_RIGHT,ImageIO.read(new File(path),o.8f))
Positions.BOTTOM_RIGHT:指明水印的位置,右下方;0.8f:透明度。
outputQuality(0.8f):图片质量,即压缩文件大小。
toFile()生成新的文件。
2.PathUtil类
package com.imooc.o2o.util;
public class PathUtil {
//不同系统的分隔符不一样,因此根据系统选择不同的分隔符
private static String seperator = System.getProperty("file.separator");
/**
* 返回系统存图片的根目录
* @return
*/
public static String getImgBasePath() {
//获取系统类型
String os = System.getProperty("os.name");
String basePath = "";
if (os.toLowerCase().startsWith("win")) {
basePath = "D:/projectdev/image/";
} else {
basePath = "/home/us/image/";
}
basePath = basePath.replace("/", seperator);
return basePath;
}
/**
* 返回项目图片相对路径
* @param shopId
* @return
*/
public static String getShopImagePath(long shopId) {
String imagePath = "upload/item/shop/" + shopId + "/";
return imagePath.replace("/", seperator);
}
}
本类的作用是获取图片的相对路径(upload/item/shop/ shopid /)
根目录(D:/projectdev/image/)
为什么不把图片路径设置在classpath下?
注意:一旦将图片路径设置在classpath,如果工程重新部署,新生成的文件图片就会被删除,除非文件一开始就保存在classpath下,但程序运行过程中,用户会上传新的图片。因此需要将图片存储地址设置在根路径以外,以防止它自动被删除掉。也有公司将图片保存在其他服务器,通过URL引入进来。
3.ImageUtil
package com.imooc.o2o.util;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import javax.imageio.ImageIO;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
public class ImageUtil {
private static String basePath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
private static SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
private static final Random random = new Random();
/**
* 保存用户上传图片到指定位置
* @param thumbnail
* @param targetAddr
* 由于会存在用户上传图片名字会重复的情况,因此,需要我们统一对图片重命名(年月日分秒+5为随机数+扩展名)
* @return
*/
public static String generateThumbnail(File thumbnail, String targetAddr) {
String realFileName = getRandomFileName();
String extension = getFileExtension(thumbnail);
makeDirPath(targetAddr);
String relativeAddr = targetAddr + realFileName + extension;
File dest = new File(PathUtil.getImgBasePath() + relativeAddr);
try {
Thumbnails.of(thumbnail).size(200, 200)
.watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File(basePath + "/watermark.jpg")), 0.25f)
.outputQuality(0.8f).toFile(dest);
} catch (IOException e) {
e.printStackTrace();
}
return relativeAddr;
}
public static String generateThumbnail(CommonsMultipartFile thumbnail, String targetAddr) {
String realFileName = getRandomFileName();
String extension = getFileExtension(thumbnail);
makeDirPath(targetAddr);
String relativeAddr = targetAddr + realFileName + extension;
File dest = new File(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 (IOException e) {
e.printStackTrace();
}
return relativeAddr;
}
/**
* 生成随机文件名,当前的年月日小时分钟秒钟+五位随机数
*
* @return
*/
private static String getRandomFileName() {
// 随机五位数
int rannum = random.nextInt (89999) + 10000;
String nowTimeStr = sDateFormat.format(new Date());
return nowTimeStr+rannum;
}
/**
* 获取输入文件流的扩展名
* 由于会存在用户上传图片名字会重复的情况,因此,需要我们统一对图片重命名 (年月日分秒+5为随机数+扩展名)
* @param thumbnail
* @return
*/
private static String getFileExtension(File thumbnail) {
String originalFilename = thumbnail.getName();
return originalFilename.substring(originalFilename.lastIndexOf("."));
//return thumbnail.getName().substring(thumbnail.getName().lastIndexOf("."), thumbnail.getName().length());
}
private static String getFileExtension(CommonsMultipartFile thumbnail) {
String originalFilename = thumbnail.getOriginalFilename();
return originalFilename.substring(originalFilename.lastIndexOf("."));
//return thumbnail.getName().substring(thumbnail.getName().lastIndexOf("."), thumbnail.getName().length());
}
/**
* 创建目标路径所涉及到的目录,/home/work/zz/xxx.jpg
* 每层目录都要创建
* @param targetAddr
*/
private static void makeDirPath(String targetAddr) {
String realFileParentPath = PathUtil.getImgBasePath() + targetAddr;
File file = new File(realFileParentPath);
if (!file.exists()) {
file.mkdirs();//递归创建目录
}
}
public static void main(String[] args) throws IOException {
/*
* String basePath =
* Thread.currentThread().getContextClassLoader().getResource("").getPath();
* System.out.println(Thread.currentThread().getContextClassLoader().getResource
* ("").getPath()); Thumbnails.of(new
* File("D:/eclipse/background.jpg")).size(500, 500)
* .watermark(Positions.BOTTOM_RIGHT, ImageIO.read(new File(basePath +
* "/logo.jpg")), 0.8f)
* .outputQuality(0.8f).toFile("D:/eclipse/background-1.jpg");
*/
File file = new File("D:/eclipse/background.jpg");
}
}
处理图片,并返回图片的存放地址(相对路径):generateThumbnail(CommonsMultipartFile file,String targetAddr);
获取时间+5位随机数:geiRandomFileName()
获取文件拓展名:getFileExtension()
递归创建相对路径:makeDirPath(String addr)
用户上传的图片名称可能会重复,因此,我们不使用用户上传图片的文件名,而是统一生成随机的文件名来保证文件不重复。
- 使用 年月日分秒+随机5位数+文件扩展名来组成新的文件名。
为什么generateThumbnail返回的是相对地址,而非绝对地址?
解析:如果迁移到别的系统上,也是照常能够读取图片,而不需要去改变数据表中shop_img的值。因此需要将shop_img的值存成相对路径的形式。这个图片读出来的时候,会动态给它拼上存储的根路径,进而不管运行在那个系统上,都能读取图片,这样就能达到解耦的功能了。