Spring Boot开发图片上传并添加水印接口

简介: 现在越来越注重版本的问题,所以很多的文章都需要进行署名,类似于这样:

1 前言


现在越来越注重版本的问题,所以很多的文章都需要进行署名,类似于这样:


3ab28fd2d0be43aaa03c0ca40754e127~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


而且很多的图片网站也为了版权的考虑而采用一些技术,反正别人的随意传播或者用于商业途径,水印技术就是为了图片版权的重要技术之一了,类似这张图片右下角的水印:


8932ce82e9ff43aba8a4bf3145b4cb0a~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


最近公司也刚好由于业务需求,需要对使用的到图片添加水印操作,这篇文章就来说说如何使用springboot来实现图片上传并添加水印。


2 正文


这里不再对过程进行一一的赘述,直接上代码,详细的功能和用法都会写在注释里,并且代码的源码也会同步至github。

完整的项目工程如下,本文相关的为绿色文件(先添加的):


91871a79f4214f259c604819b3003cec~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


先来贴出这里使用的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进行功能测试:


首先我们使用的两张原图是:


efa76d765b6e4e6e9d518a624d2d5e99~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg    

ae0bb456145a4aec9d8c620475e51de9~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


1c089b4b43b046598355617c05c9fbbf~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


3b271a6152f94cbdae2485b96b629ff3~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


77b5d7b3dda7423a95314124226bcad6~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


添加水印后的图片的效果如下:


22ab6c6f85b44eb8b22d3d8bcba8fe4a~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


dcc5ed98a13f4b92ab96380894ba2737~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


3 总结


上面就是如果使用springboot开发一个上传图片和添加水印的接口,其实该功能的实现和springboot并没有太大的关系,主要的核心代码就那么一块,有任何问题欢迎交流讨论。


另外所有实战文章的源码都会同步至github,有需要的欢迎下载使用。

目录
相关文章
|
5天前
|
Java API 微服务
【Spring Boot系列】通过OpenAPI规范构建微服务服务接口
【4月更文挑战第5天】通过OpenAPI接口构建Spring Boot服务RestAPI接口
|
22天前
|
NoSQL Java Redis
SpringBoot集成Redis解决表单重复提交接口幂等(亲测可用)
SpringBoot集成Redis解决表单重复提交接口幂等(亲测可用)
103 0
|
23天前
|
Java API Spring
SpringBoot项目调用HTTP接口5种方式你了解多少?
SpringBoot项目调用HTTP接口5种方式你了解多少?
75 2
|
27天前
|
Java 应用服务中间件 Maven
SpringBoot 项目瘦身指南
SpringBoot 项目瘦身指南
40 0
|
26天前
|
安全 Java 数据安全/隐私保护
【深入浅出Spring原理及实战】「EL表达式开发系列」深入解析SpringEL表达式理论详解与实际应用
【深入浅出Spring原理及实战】「EL表达式开发系列」深入解析SpringEL表达式理论详解与实际应用
57 1
|
26天前
|
存储 XML 缓存
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache功能的开发实战指南(一)
【深入浅出Spring原理及实战】「缓存Cache开发系列」带你深入分析Spring所提供的缓存Cache功能的开发实战指南
60 0
|
6天前
|
JSON Java fastjson
Spring Boot 底层级探索系列 04 - Web 开发(2)
Spring Boot 底层级探索系列 04 - Web 开发(2)
15 0
|
6天前
|
安全 Java 应用服务中间件
江帅帅:Spring Boot 底层级探索系列 03 - 简单配置
江帅帅:Spring Boot 底层级探索系列 03 - 简单配置
24 0
江帅帅:Spring Boot 底层级探索系列 03 - 简单配置
|
6天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
8天前
|
XML Java C++
【Spring系列】Sping VS Sping Boot区别与联系
【4月更文挑战第2天】Spring系列第一课:Spring Boot 能力介绍及简单实践
【Spring系列】Sping VS Sping Boot区别与联系