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

839 阅读3分钟

小知识,大挑战!本文正在参与“   程序员必备小知识   ”创作活动

作者的其他平台:

| CSDN:blog.csdn.net/qq_4115394…

| 掘金:juejin.cn/user/651387…

| 知乎:www.zhihu.com/people/1024…

| GitHub:github.com/JiangXia-10…

| 公众号:1024笔记

本文大概7611字,读完共需20分钟

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,有需要的欢迎下载使用。

最后如果觉得本文写得不错,就点下赞和关注推荐给更多的人呗。

今日推荐

Postman接口测试图文教程

SpringBoot开发Restful风格的接口实现CRUD功能

SpringBoot整合JPA进行数据访问

SpringBoot入门:使用IDEA和Eclipse构建第一个SpringBoot项目

SpringBoot整合Druid配置数据源监控