Use Tencent Cloud to upload pictures and add watermarks to the pictures

controller layer

@ApiOperation("上传")
@PostMapping("/upload")
//@RequiresRoles("admin")
public Result upload(
    @ApiParam(value = "文件", required = true) @RequestParam("file") MultipartFile multipartFile,
    @ApiParam(value = "是否加水印:0-不加,1-加")@RequestParam(defaultValue = "0") Integer isWaterMark
) {

    Result result = new Result();

    //将文件上传到腾讯云
    try {
        if (isWaterMark == 1) {
            //加水印
            multipartFile = WaterMarkUtils.addWorkMarkToMutipartFile(multipartFile, "找房快");
        }

        //上传腾讯云,返回随机文件名字
        File file = MultipartFileUtil.multipartFileToFile(multipartFile);
        String filename = TengXunOssUtil.uploadFile(file);
        filename = TengXunOssUtil.URL_PREFIX + filename;//拼接访问路径和文件名

		//删除本地临时文件
        MultipartFileUtil.delteTempFile(file);
        result.setCode(200);
        result.setResult(filename);
        result.setMessage("上传成功");
    } catch (Exception e) {
        log.info(e.getMessage(), e);
        result.setCode(500);
        result.setMessage("上传失败");

    }
    return result;
}

Image upload tool

import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @author 
 * @version 1.0
 * @date 2021/1/6 15:40
 */
public class WaterMarkUtils {

    /**
     * 加图片水印 : 没有测试
     *
     * @param bufImg  --BufferedImage  用来画图的宽高跟需要加水印的图片一样的空白图
     * @param img --需要加水印的图片
     * @param markImg --水印图片
     * @param width	--水印图片宽
     * @param height --水印图片高
     * @param x	--水印相对于底片的x轴坐标(PS:左上角为(0,0))
     * @param y  --水印相对于底片的y轴坐标(PS:左上角为(0,0))
     */
    public static void markPic(BufferedImage bufImg, Image img, Image markImg, int width, int height, int x, int y) {
        //取到画笔
        Graphics2D g = bufImg.createGraphics();
        //画底片
        g.drawImage(img, 0, 0, bufImg.getWidth(), bufImg.getHeight(), null);
        //画水印位置
        g.drawImage(markImg, x, y, width, height, null);
        g.dispose();
    }

    /**
     * 直接给multipartFile加上图片水印再进行保存图片的操作方便省事
     *
     * @param multipartFile
     *            文件上传的对象
     * @param markImg
     *            水印文件的路径 如果是相对路径请使用相对路径new Image的方法,此处用的是url
     * @return
     * @throws IOException
     * @author 高永强
     * @version 2018年11月30日 上午11:15:56
     */
    public static MultipartFile addPicMarkToMutipartFile(MultipartFile multipartFile,
                                                         String markImg) throws IOException {
        // 获取图片文件名 xxx.png xxx
        String originFileName = multipartFile.getOriginalFilename();
        // 获取原图片后缀 png
        int lastSplit = originFileName.lastIndexOf(".");
        String suffix = originFileName.substring(lastSplit + 1);
        // 获取图片原始信息
        String dOriginFileName = multipartFile.getOriginalFilename();
        String dContentType = multipartFile.getContentType();
        // 是图片且不是gif才加水印
        if (!suffix.equalsIgnoreCase("gif") && dContentType.contains("image")) {
            // 获取水印图片
            InputStream inputImg = multipartFile.getInputStream();
            Image img = ImageIO.read(inputImg);
            URL url = new URL(markImg);
            // 创建url连接;
            HttpURLConnection urlconn = (HttpURLConnection) url.openConnection();
            urlconn.connect();
            InputStream inputStream = urlconn.getInputStream();
            Image mark = ImageIO.read(inputStream);

            // 加图片水印
            int imgWidth = img.getWidth(null);
            int imgHeight = img.getHeight(null);

            int markWidth = mark.getWidth(null);
            int markHeight = mark.getHeight(null);

            BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight,
                BufferedImage.TYPE_INT_RGB);
            //水印的相对位置  ps:这里是右下角  水印宽为底片的四分之一  位置自己可以调整
            markPic(bufImg, img, mark, imgWidth / 4, (imgWidth * markHeight) / (4 * markWidth),
                imgWidth - imgWidth / 4, imgHeight - (imgWidth * markHeight) / (4 * markWidth));
            ByteArrayOutputStream bs = new ByteArrayOutputStream();
            ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
            ImageIO.write(bufImg, suffix, imOut);
            InputStream is = new ByteArrayInputStream(bs.toByteArray());

            // 加水印后的文件上传
            multipartFile = new MockMultipartFile(dOriginFileName, dOriginFileName, dContentType, is);
        }
        //返回加了水印的上传对象
        return multipartFile;
    }

    /**
     * 加文字水印
     * @param bufImg --BufferedImage  用来画图的宽高跟需要加水印的图片一样的空白图
     * @param img --需要加水印的图片
     * @param text --水印文字
     * @param font --字体
     * @param degree --旋转角度
     * @param color --颜色
     * @param x  --水印相对于底片的x轴坐标(PS:左上角为(0,0))
     * @param y  --水印相对于底片的y轴坐标(PS:左上角为(0,0))
     * @author 高永强
     * @version 2018年11月30日 上午11:39:57
     */
    public static void markWord(BufferedImage bufImg, Image img, String text, Font font, Color color,Integer degree, int x, int y) {
        //取到画笔
        Graphics2D g = bufImg.createGraphics();
        //画底片
        g.drawImage(img, 0, 0, bufImg.getWidth(), bufImg.getHeight(), null);
        g.setColor(color);//设置水印颜色
        //g.setFont(font);//设置字体.设置字体后台linux系统中无法打印,故注释掉
        float alpha = 0.5f;//设置水印透明度 默认为1.0  值越小颜色越浅
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));//设置水印文字透明度
        if (null != degree) {
            g.rotate(Math.toRadians(degree),(double)bufImg.getWidth(),(double)bufImg.getHeight());//设置水印旋转
        }
        //位置
        g.drawString(text, x, y);
        JLabel label = new JLabel(text);
        FontMetrics metrics = label.getFontMetrics(font);
        int width = metrics.stringWidth(label.getText());//文字水印的宽
        int srcImgHeight = bufImg.getHeight();
        int srcImgWidth = bufImg.getWidth();
        int rowsNumber = srcImgHeight/width+srcImgHeight%width;// 图片的高  除以  文字水印的宽  打印的行数(以文字水印的宽为间隔)
        int columnsNumber = srcImgWidth/width+srcImgWidth%width;//图片的宽 除以 文字水印的宽  每行打印的列数(以文字水印的宽为间隔)
        //防止图片太小而文字水印太长,所以至少打印一次
        if(rowsNumber < 1){
            rowsNumber = 1;
        }
        if(columnsNumber < 1){
            columnsNumber = 1;
        }
        for(int j=0;j<rowsNumber;j++){
            for(int i=0;i<columnsNumber;i++){
                g.drawString(text, i*width + j*width, -i*width + j*width);//画出水印,并设置水印位置
            }
        }
        g.dispose();// 释放资源

    }

    /**
     * 直接给multipartFile加上文字水印再进行保存图片的操作方便省事
     *
     * @param multipartFile
     *            文件上传的对象
     * @param markImg
     *            水印文件的路径 如果是相对路径请使用相对路径new Image的方法,此处用的是url
     * @return
     * @throws IOException
     * @author 高永强
     * @version 2018年11月30日 上午11:15:56
     */
    public static MultipartFile addWorkMarkToMutipartFile(MultipartFile multipartFile,
                                                          String word) throws IOException {
        // 获取图片文件名 xxx.png xxx
        String originFileName = multipartFile.getOriginalFilename();
        // 获取原图片后缀 png
        int lastSplit = originFileName.lastIndexOf(".");
        String suffix = originFileName.substring(lastSplit + 1);
        // 获取图片原始信息
        String dOriginFileName = multipartFile.getOriginalFilename();
        String dContentType = multipartFile.getContentType();
        // 是图片且不是gif才加水印
        if (!suffix.equalsIgnoreCase("gif") && dContentType.contains("image")) {
            // 获取水印图片
            InputStream inputImg = multipartFile.getInputStream();
            Image img = ImageIO.read(inputImg);
            // 加图片水印
            int imgWidth = img.getWidth(null);
            int imgHeight = img.getHeight(null);

            BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight,
                BufferedImage.TYPE_INT_RGB);
            //设置字体
            Font font = new Font("宋体", Font.PLAIN, 14);
            //调用画文字水印的方法
            markWord(bufImg, img, word, font , Color.white,-45, imgWidth/8, imgHeight/8);
            ByteArrayOutputStream bs = new ByteArrayOutputStream();
            ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
            ImageIO.write(bufImg, suffix, imOut);
            InputStream is = new ByteArrayInputStream(bs.toByteArray());

            // 加水印后的文件上传
            multipartFile = new MockMultipartFile(dOriginFileName, dOriginFileName, dContentType,
                is);
        }
        //返回加了水印的上传对象
        return multipartFile;
    }
    
}

MultipartFile to File tool


import org.springframework.web.multipart.MultipartFile;

import java.io.*;

/**
 * @author 卿通胜
 * @version 1.0
 * @date 2020/9/11 9:41
 */
public class MultipartFileUtil {

    /**
     * MultipartFile 转 File
     *
     * @param file
     * @throws Exception
     */
    public static File multipartFileToFile(MultipartFile file){

        File toFile = null;
        if (file.equals("") || file.getSize() <= 0) {
            file = null;
        } else {
            InputStream ins = null;
            try {
                ins = file.getInputStream();
                toFile = new File(file.getOriginalFilename());
                inputStreamToFile(ins, toFile);
                ins.close();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (ins != null) {
                    try {
                        ins.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return toFile;
    }

    //获取流文件
    private static void inputStreamToFile(InputStream ins, File file) {
        OutputStream os = null;
        try {
            os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //释放资源
            if (ins != null) {
                try {
                    ins.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.flush();
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
        }
    }

    /**
     * 删除本地临时文件: 
     * @param file
     */
    public static void delteTempFile(File file) {
        if (file != null) {
            File del = new File(file.toURI());
            del.delete();
        }
    }
}

File upload dependency

<!--腾讯云oss-->
<dependency>
	<groupId>com.qcloud</groupId>
	<artifactId>cos_api</artifactId>
	<version>5.6.24</version>
</dependency>

Tencent Cloud file upload

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.model.*;
import com.qcloud.cos.region.Region;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.utils.UuidUtils;

import java.io.File;
import java.util.List;

/**
 * 腾讯云oss
 *
 * @author 卿通胜
 * @version 1.0
 * @date 2020/9/8 15:29
 */
@Slf4j
public class TengXunOssUtil {

    public static final String URL_PREFIX = "https://findhouse-1302106834.cos.ap-chongqing.myqcloud.com/";

    // 1 初始化用户身份信息(secretId, secretKey)。
    private static String secretId = "填写腾讯云cos密钥id";
    private static String secretKey = "填写腾讯云cos密钥key";
    private static COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);

    private static String bucket = "填写存储桶名称"; //存储桶名称,格式:BucketName-APPID

    // 2 设置 bucket 的区域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
    // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
    private static Region region = new Region("ap-chongqing");
    private static ClientConfig clientConfig = new ClientConfig(region);
    // 3 生成 cos 客户端。
    private static COSClient cosClient = new COSClient(cred, clientConfig);


    /**
     * 查询存储桶列表
     *
     * @return
     */
    public static List<Bucket> getBuckets() {
        List<Bucket> buckets = cosClient.listBuckets();
        for (Bucket bucketElement : buckets) {
            String bucketName = bucketElement.getName();
            String bucketLocation = bucketElement.getLocation();
        }
        return buckets;
    }

    /**
     * 上传文件
     *
     * @param localFile
     * @return 文件名称
     */
    public static String uploadFile(File localFile) {

        // 指定要上传到 COS 上对象键
        String filename = localFile.getName();
        String suffix = filename.substring(filename.lastIndexOf("."));//文件后缀
        filename = UuidUtils.getUUID() + suffix;

        PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, filename, localFile);
        PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);

        return filename;
    }

    /**
     * 删除文件
     *
     * @param fileName 文件名称
     */
    public static void deletefile(String fileName) throws CosClientException, CosServiceException {

        // 生成cos客户端
        COSClient cosclient = new COSClient(cred, clientConfig);

        //处理图片名称
        if (fileName.contains(TengXunOssUtil.URL_PREFIX)) {
            //如果文件名中包含了url前缀,则去掉
            fileName = fileName.replace(TengXunOssUtil.URL_PREFIX, "");
        }
        // 指定要删除的 bucket 和路径
        cosclient.deleteObject(bucket, fileName);

        // 关闭客户端(关闭后台线程)
        cosclient.shutdown();

    }

    /**
     *
     * @describe 上传文件的方法
     * @methods uploadObject 方法名
     * @param  fileUrl 上传文件地址
     * @param  fileKey 文件对象名称
     * @parameter @return 对象列表
     */
    public PutObjectResult uploadObject(String fileUrl, String fileKey) {
        try {
            // 指定要上传的文件
            File localFile = new File(fileUrl);
            // fileKey 指定要上传到 COS 上对象键
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, fileKey, localFile);
            PutObjectResult  putObjectResult = cosClient.putObject(putObjectRequest);
            return putObjectResult;
        } catch (CosServiceException serverException) {
            log.error(serverException.getErrorMessage());
            throw  new RuntimeException("上传文件平台Server异常"+serverException.getErrorMessage());
        } catch (CosClientException clientException) {
            log.error(clientException.getMessage());
            throw  new RuntimeException("上传文件平台Client异常"+clientException.getMessage());
        }

    }


    //测试
    /*public static void main(String [] args){
        try {

            File localFile = new File("F:\\找房快.jpg");
            uploadFile(localFile);

        }catch (Exception e){
            e.printStackTrace();
        }
    }*/

    /**
     * 测试删除
     * @param args
     */
    /*public static void main(String[] args) {
        deletefile("clipboard.png");
    }*/


}

Picture effect
Insert picture description here

Solve the problem of uploading pictures to the server watermark text display box does not display text, java local Chinese is displayed correctly, the server becomes mouth-to-mouth
Go here: https://blog.csdn.net/lhq186/article/details/98621405

Guess you like

Origin blog.csdn.net/weixin_44684303/article/details/112515144