1 前言
现在越来越注重版本的问题,所以很多的文章都需要进行署名,类似于这样:
而且很多的图片网站也为了版权的考虑而采用一些技术,反正别人的随意传播或者用于商业途径,水印技术就是为了图片版权的重要技术之一了,类似这张图片右下角的水印:
最近公司也刚好由于业务需求,需要对使用的到图片添加水印操作,这篇文章就来说说如何使用springboot来实现图片上传并添加水印。
2 正文
这里不再对过程进行一一的赘述,直接上代码,详细的功能和用法都会写在注释里,并且代码的源码也会同步至github。
完整的项目工程如下,本文相关的为绿色文件(先添加的):
先来贴出这里使用的pom文件:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> <!-- springboot 整合 log4j --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j</artifactId> <version>1.3.8.RELEASE</version> </dependency> </dependencies> 复制代码
接着我这里写了几个使用到的工具类:
首先是web相关接口的返回状态的枚举:
package com.springboot.springbootdemo.util; /** * Description: web相关接口返回状态枚举 */ public enum ReturnCodeAndMsgEnum { Success(0, "ok"), No_Data(-1, "no data"), SYSTEM_ERROR(10004, "system error"); private String msg; private int code; private ReturnCodeAndMsgEnum(int code, String msg) { this.code = code; this.msg = msg; } public static ReturnCodeAndMsgEnum getByCode(int code) { ReturnCodeAndMsgEnum[] var1 = values(); int var2 = var1.length; for(int var3 = 0; var3 < var2; ++var3) { ReturnCodeAndMsgEnum aiTypeEnum = var1[var3]; if (aiTypeEnum.code == code) { return aiTypeEnum; } } return Success; } public String getMsg() { return this.msg; } public int getCode() { return this.code; } } 复制代码
接着封装web的返回结果:
package com.springboot.springbootdemo.util; import java.io.Serializable; /** * Description: 统一web返回结果 */ public class ReturnValue<T> implements Serializable { private static final long serialVersionUID = -1959544190118740608L; private int ret; private String msg; private T data; public ReturnValue() { this.ret = 0; this.msg = ""; this.data = null; } public ReturnValue(int retCode, String msg, T data) { this.ret = 0; this.msg = ""; this.data = null; this.ret = retCode; this.data = data; this.msg = msg; } public ReturnValue(int retCode, String msg) { this.ret = 0; this.msg = ""; this.data = null; this.ret = retCode; this.msg = msg; } public ReturnValue(ReturnCodeAndMsgEnum codeAndMsg) { this(codeAndMsg.getCode(), codeAndMsg.getMsg(), null); } public ReturnValue(ReturnCodeAndMsgEnum codeAndMsg, T data) { this(codeAndMsg.getCode(), codeAndMsg.getMsg(), data); } public int getRet() { return this.ret; } public void setRet(int ret) { this.ret = ret; } public String getMsg() { return this.msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return this.data; } public void setData(T data) { this.data = data; } @Override public String toString() { return "ReturnValue{" + "ret=" + ret + ", msg='" + msg + '\'' + ", data=" + data + '}'; } } 复制代码
最后就是添加水印的工具类:
package com.springboot.springbootdemo.util; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.InputStream; import java.io.OutputStream; import javax.imageio.ImageIO; /** * 图片水印工具类 */ public class WaterMarkUtil { // 水印文字字体 private static Font font = new Font("宋体", Font.BOLD, 20); // 水印文字颜色 private static Color color = Color.red; // 水印透明度 private static float alpha = 0.3f; // 水印横向位置 private static int positionWidth = 50; // 水印纵向位置 private static int positionHeight = 100; /** * 添加水印的方法 */ public static void ImagemarkWater(String text, InputStream inputStream, OutputStream outputStream, Integer degree, String typeName) { try { // 1、源图片 Image srcImg = ImageIO.read(inputStream); int imgWidth = srcImg.getWidth(null); int imgHeight = srcImg.getHeight(null); BufferedImage buffImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB); // 2、得到画笔对象 Graphics2D g = buffImg.createGraphics(); // 3、设置对线段的锯齿状边缘处理 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.drawImage(srcImg.getScaledInstance(imgWidth, imgHeight, Image.SCALE_SMOOTH), 0, 0, null); // 4、设置水印的旋转角度 if (null != degree) { g.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2); } // 5、设置水印文字颜色 g.setColor(color); // 6、设置水印文字Font g.setFont(font); // 7、设置水印文字透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); // 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y) g.drawString(text, positionWidth, positionHeight); // 9、释放资源 g.dispose(); // 10、生成图片 ImageIO.write(buffImg, typeName.toUpperCase(), outputStream); } catch (Exception e) { e.printStackTrace(); } } } 复制代码
接下来就是service层代码:
package com.springboot.springbootdemo.service; import com.springboot.springbootdemo.util.ReturnValue; import org.springframework.web.multipart.MultipartFile; public interface ImageFileService { public ReturnValue uploadImageFileTest(MultipartFile imageFile); } 复制代码
package com.springboot.springbootdemo.service; import com.springboot.springbootdemo.util.ReturnCodeAndMsgEnum; import com.springboot.springbootdemo.util.ReturnValue; import com.springboot.springbootdemo.util.WaterMarkUtil; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.*; import java.util.UUID; @Service public class ImageFileServiceImp implements ImageFileService { private static final Logger logger = LoggerFactory.getLogger(ImageFileServiceImp.class); @Override public ReturnValue uploadImageFileTest(MultipartFile imgFile) { //文件保存路径 String targetFilePath = "C:\\Users\\Jiang\\Desktop\\测试"; //重命名保存新文件的文件名 String fileName = UUID.randomUUID().toString().replace("-", ""); File targetFile = new File(targetFilePath + File.separator + fileName); try{ String originalFilename = imgFile.getOriginalFilename(); String typeName = originalFilename.substring(originalFilename.indexOf(".")+1 ,originalFilename.length()); InputStream inputStream = imgFile.getInputStream(); OutputStream outputStream = new FileOutputStream(targetFile) ; //调用添加水印的方法 WaterMarkUtil.ImagemarkWater("1024笔记", inputStream, outputStream, 0, typeName); outputStream.close(); inputStream.close(); logger.info("------图片上传、添加水印成功------"); }catch(IOException e){ } return new ReturnValue<>(ReturnCodeAndMsgEnum.Success, null); } } 复制代码
Controller层代码:
package com.springboot.springbootdemo.controller; import com.springboot.springbootdemo.service.ImageFileService; import com.springboot.springbootdemo.util.ReturnValue; import com.springboot.springbootdemo.util.WaterMarkUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; @RestController @RequestMapping(value = "/image") public class ImageFileController { private static final Logger logger = LoggerFactory.getLogger(ImageFileController.class); @Autowired private ImageFileService imageFileService; /** * 文件上传测试接口 * @return */ @RequestMapping("/upload") public ReturnValue uploadFileTest(@RequestParam("uploadFile") MultipartFile imgFile) { return imageFileService.uploadImageFileTest(imgFile); } } 复制代码
接下来启动项目,使用postman进行功能测试:
首先我们使用的两张原图是:
添加水印后的图片的效果如下:
3 总结
上面就是如果使用springboot开发一个上传图片和添加水印的接口,其实该功能的实现和springboot并没有太大的关系,主要的核心代码就那么一块,有任何问题欢迎交流讨论。
另外所有实战文章的源码都会同步至github,有需要的欢迎下载使用。