springboot 生成二维码上传至oss

需求说明:根据个数生成二维码,二维码存放地址阿里oss

1、第三方类

 <!-- 二维码支持包 -->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.3.3</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.3.3</version>
        </dependency>
                <!-- 阿里云oss -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.10.2</version>
        </dependency>

2、创建二维码工具类

package com.shouchuang.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.HashMap;

@Slf4j
@Component
public class QrCodeUtil {
    /**
    * 默认宽度
    */
    private static final Integer WIDTH = 140;

    /**
    * 默认高度
    */
    private static final Integer HEIGHT = 140;

    /**
    * LOGO 默认宽度
    */
    private static final Integer LOGO_WIDTH = 22;

    /**
    * LOGO 默认高度
    */
    private static final Integer LOGO_HEIGHT = 22;

    /**
    * 图片格式
    */
    private static final String IMAGE_FORMAT = "png";

    private static final String CHARSET = "utf-8";

    /**
    * 原生转码前面没有 data:image/png;base64 这些字段,返回给前端是无法被解析
    */
    private static final String BASE64_IMAGE = "data:image/png;base64,%s";

    /**
    * 生成二维码,使用默认尺寸
    *
    * @param content 内容
    * @return
    */
    public String getBase64QRCode(String content) {
        return getBase64Image(content, WIDTH, HEIGHT, null, null, null);
    }


    /**
      * 生成二维码
      *
      * @param content    内容
      * @param width      二维码宽度
      * @param height     二维码高度
      * @param logoUrl    logo 在线地址
      * @param logoWidth  logo 宽度
      * @param logoHeight logo 高度
      * @return
      */
    public String getBase64QRCode(String content, Integer width, Integer height, String logoUrl, Integer logoWidth, Integer logoHeight) {
        return getBase64Image(content, width, height, logoUrl, logoWidth, logoHeight);
    }

    private String getBase64Image(String content, Integer width, Integer height, String logoUrl, Integer logoWidth, Integer logoHeight) {

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        BufferedImage bufferedImage = crateQRCode(content, width, height, logoUrl, logoWidth, logoHeight);
        try {
            ImageIO.write(bufferedImage, IMAGE_FORMAT, os);
        } catch (IOException e) {
            log.error("[生成二维码,错误{}]", e);
        }
        // 转出即可直接使用
        return String.format(BASE64_IMAGE, Base64.encode(os.toByteArray()));


    }

    /**
     * 生成二维码
     *
     * @param content    内容
     * @param width      二维码宽度
     * @param height     二维码高度
     * @param logoUrl    logo 在线地址
     * @param logoWidth  logo 宽度
     * @param logoHeight logo 高度
     * @return
     */
    private BufferedImage crateQRCode(String content, Integer width, Integer height, String logoUrl, Integer logoWidth, Integer logoHeight) {
        if (StrUtil.isNotBlank(content)) {
            ServletOutputStream stream = null;

            HashMap<EncodeHintType, Comparable> hints = new HashMap<>(4);
            // 指定字符编码为utf-8
            hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
            // 指定二维码的纠错等级为中级
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            // 设置图片的边距
            hints.put(EncodeHintType.MARGIN, 2);
            try {
                QRCodeWriter writer = new QRCodeWriter();
                BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
                BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                for (int x = 0; x < width; x++) {
                    for (int y = 0; y < height; y++) {
                        bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
                    }
                }
                if (StrUtil.isNotBlank(logoUrl)) {
                    insertLogo(bufferedImage, width, height, logoUrl, logoWidth, logoHeight);
                }
                return bufferedImage;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (stream != null) {
                    try {
                        stream.flush();
                        stream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return null;
    }

    /**
     * 二维码插入logo
     *
     * @param source     二维码
     * @param width      二维码宽度
     * @param height     二维码高度
     * @param logoUrl    logo 在线地址
     * @param logoWidth  logo 宽度
     * @param logoHeight logo 高度
     * @throws Exception
     */
    private void insertLogo(BufferedImage source, Integer width, Integer height, String logoUrl, Integer logoWidth, Integer logoHeight) throws Exception {
        // logo 源可为 File/InputStream/URL
        Image src = ImageIO.read(new URL(logoUrl));
        // 插入LOGO
        Graphics2D graph = source.createGraphics();
        int x = (width - logoWidth) / 2;
        int y = (height - logoHeight) / 2;
        graph.drawImage(src, x, y, logoWidth, logoHeight, null);
        Shape shape = new RoundRectangle2D.Float(x, y, logoWidth, logoHeight, 6, 6);
        graph.setStroke(new BasicStroke(3f));
        graph.draw(shape);
        graph.dispose();
    }

    /**
     * 获取二维码
     *
     * @param content 内容
     * @throws IOException
     */
    public void getQRCode(String content,OutputStream output) throws IOException {
        BufferedImage image = crateQRCode(content, WIDTH, HEIGHT, null, null, null);
        ImageIO.write(image, IMAGE_FORMAT, output);
    }

    /**
     * 获取二维码
     *
     * @param content 内容
     * @param logoUrl logo资源
     * @param output  输出流
     * @throws Exception
     */
    public void getQRCode(String content, String logoUrl, OutputStream output) throws Exception {
        BufferedImage image = crateQRCode(content, WIDTH, HEIGHT, logoUrl, LOGO_WIDTH, LOGO_HEIGHT);
        ImageIO.write(image, IMAGE_FORMAT, output);
    }




}

3、在yml文件中增加oss配置项目

oss:
  access-key-id: XXXXXX
  access-key-secret: XXXXXX
  bucket: shouchuangzichan
  endpoint: XXXXXXX
  dir: file/
  oss-url: XXXXX

4、创建config包,增加oss属性类,属性类中引入了yml中的属性,根据你的属性配置名称修改

package com.shouchuang.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;


@Component
@ConfigurationProperties(prefix = "oss")
public class OSSProperties{

    private String endpoint;

    private String accessKeyId;

    private String accessKeySecret;

    private String bucket;

    private String dir;

    //省略getset

    public String getEndpoint() {
        return endpoint;
    }

    public void setEndpoint(String endpoint) {
        this.endpoint = endpoint;
    }

    public String getAccessKeyId() {
        return accessKeyId;
    }

    public void setAccessKeyId(String accessKeyId) {
        this.accessKeyId = accessKeyId;
    }

    public String getAccessKeySecret() {
        return accessKeySecret;
    }

    public void setAccessKeySecret(String accessKeySecret) {
        this.accessKeySecret = accessKeySecret;
    }

    public String getBucket() {
        return bucket;
    }

    public void setBucket(String bucket) {
        this.bucket = bucket;
    }

    public String getDir() {
        return dir;
    }

    public void setDir(String dir) {
        this.dir = dir;
    }
}

5、新增config配置类,主要实例oss对象方便项目使用

package com.shouchuang.config;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class OSSConfig {

    @Autowired
    private OSSProperties ossProperties;

    @Bean
    public OSSClient ossClient(){

        OSS ossClient = new OSSClientBuilder().build(ossProperties.getEndpoint(),
                ossProperties.getAccessKeyId(),
                ossProperties.getAccessKeySecret());
        return (OSSClient) ossClient;
    }
}

6、新增oss工具类,方便项目逻辑中调用上传等方法

package com.shouchuang.utils;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import com.shouchuang.config.OSSProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;

@Component
public class OSSUtil {

    @Autowired
    private OSSProperties ossProperties;

    @Autowired
    private OSSClient ossClient;

    @Autowired
    private Environment env;

    /**
     * 上传图片
     *
     * @param file
     * @param fileName
     * @return
     * @throws IOException
     */
    public String uploadImg2Oss(MultipartFile file, String fileName) throws IOException {
        try {
            InputStream inputStream = file.getInputStream();

            this.uploadFile2OSS(inputStream, fileName);
            String url = "https://" + env.getProperty("oss.bucket") + "." + env.getProperty("oss.endpoint") + "/" + env.getProperty("oss.dir") + fileName;
            System.out.println(url);
            return url;
        } catch (Exception e) {
            System.out.println(e.getMessage() +"图片错误");
            throw new IOException("图片上传失败");
        }
    }

    /**
     * 上传到OSS服务器 如果同名文件会覆盖服务器上的
     *
     * @param instream 文件流
     * @param fileName 文件名称 包括后缀名
     * @return 出错返回"" ,唯一MD5数字签名
     */
    public String uploadFile2OSS(InputStream instream, String fileName) {
        String ret = "";
        try {
            // 创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(instream.available());

            objectMetadata.setCacheControl("no-cache");

            objectMetadata.setHeader("Pragma", "no-cache");

            objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));

            objectMetadata.setContentDisposition("inline;filename=" + fileName);
//            System.out.println("oss-cn-beijing.aliyuncs.com");

            // 上传文件
//            PutObjectResult putResult = ossClient.putObject(ossProperties.getBucket(), ossProperties.getDir() + fileName, instream, objectMetadata);
            PutObjectResult putResult = ossClient.putObject(env.getProperty("oss.bucket"), env.getProperty("oss.dir") + fileName, instream, objectMetadata);
            System.out.println(123);
            System.out.println(putResult);

            ret = putResult.getETag();
        }
        catch (IOException e)
        {
            System.out.println(e.getMessage()+"123");
        }
        finally {
            try {
                if (instream != null) {
                    instream.close();
                }
            } catch (IOException e) {
                System.out.println(e.getMessage()+"错误信息");
                e.printStackTrace();
            }
        }
        return ret;
    }

    /**
     * Description: 判断OSS服务文件上传时文件的contentType
     */
    public static String getcontentType(String filenameExtension) {
        if (filenameExtension.equalsIgnoreCase("bmp")) {
            return "image/bmp";
        }
        if (filenameExtension.equalsIgnoreCase("gif")) {
            return "image/gif";
        }
        if (filenameExtension.equalsIgnoreCase("jpeg") || filenameExtension.equalsIgnoreCase("jpg")
                || filenameExtension.equalsIgnoreCase("png")) {
            return "image/jpeg";
        }
        if (filenameExtension.equalsIgnoreCase("html")) {
            return "text/html";
        }
        if (filenameExtension.equalsIgnoreCase("txt")) {
            return "text/plain";
        }
        if (filenameExtension.equalsIgnoreCase("vsd")) {
            return "application/vnd.visio";
        }
        if (filenameExtension.equalsIgnoreCase("pptx") || filenameExtension.equalsIgnoreCase("ppt")) {
            return "application/vnd.ms-powerpoint";
        }
        if (filenameExtension.equalsIgnoreCase("docx") || filenameExtension.equalsIgnoreCase("doc")) {
            return "application/msword";
        }
        if (filenameExtension.equalsIgnoreCase("xml")) {
            return "text/xml";
        }
        return "image/jpeg";
    }


}

7、控制器方法

package com.shouchuang.controller;

import com.shouchuang.annotation.PassToken;
import com.shouchuang.config.OSSProperties;
import com.shouchuang.dao.Admin;
import com.shouchuang.service.AdminService;
import com.shouchuang.service.QrCodeService;
import com.shouchuang.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;


import javax.servlet.http.HttpServletRequest;


@RestController
public class QrCodeController {
    @Autowired
    Environment env;

    @Autowired
    OSSProperties ossProperties;

    @Autowired
    QrCodeUtil qrCodeUtil;

    @Autowired
    OSSUtil ossUtil;

    @Autowired
    QrCodeService qrCodeService;

    @Autowired
    AdminService adminService;

    /***
     * @auth lifang
     * @info 根据数量项目下新增二维码
     * @param number 数量
     * @param request 请求
     */
    @PassToken
    @GetMapping(value = "batch/add/qrcode")
    public JSONResult add(@RequestParam Integer number, HttpServletRequest request)
    {
        try {
            //获取用户id
            String token = request.getHeader("token");
            String userId = JSONWebToken.getAudience(token);
            //获取用户信息
            Admin admin = adminService.getByUserName(userId);

            for (int i=0; i<number ;i++)
            {
                Integer bRet = qrCodeService.addCode(admin);
                if ( bRet != 1 )
                {
                    return JSONResult.errorMsg("添加失败");
                }
            }
            return JSONResult.ok();

        }
        catch (Exception e)
        {
            return JSONResult.errorMsg(e.getMessage());
        }
    }


}

8、service逻辑

package com.shouchuang.service.impl;

import com.shouchuang.dao.Admin;
import com.shouchuang.dao.QrCode;
import com.shouchuang.exception.GraceException;
import com.shouchuang.mapper.QrCodeMapper;
import com.shouchuang.service.QrCodeService;
import com.shouchuang.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

@Service
public class QrCodeServiceImpl implements QrCodeService {
    @Autowired
    QrCodeUtil qrCodeUtil;

    @Autowired
    OSSUtil ossUtil;

    @Autowired
    Environment env;

    @Autowired
    QrCodeMapper qrCodeMapper;

    @Override
    public Integer addCode(Admin admin) throws IOException {

        Long lid = SnowFlakeUtil.getSnowflakeId();
        String id = String.valueOf(lid);
        String url = creteCode(id);
        System.out.println(url);

        //生成当前时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String date = simpleDateFormat.format(new Date());

        //赋值创建二维码
        QrCode qrCode = new QrCode();
        qrCode.setId(new BigInteger(id));
        qrCode.setImg_url(url);
        qrCode.setStatus(2);
        qrCode.setLoads(0);
        qrCode.setSign_code("");
        qrCode.setAdmin_id(admin.getId());
        qrCode.setProject_id(admin.getProject());
        qrCode.setCreated_at(date);
        qrCode.setUpdated_at(date);

        return qrCodeMapper.addQrCode(qrCode);
    }

    /***
     * @auth lifang
     * @info  创建二维码上传至oss
     * @param id
     * @return
     * @throws IOException
     */
    public String creteCode(String id) throws IOException {
        //生成base64的二维码
        String base64QRCode = qrCodeUtil.getBase64QRCode("http://XXXXXXXXX:8287/code.png?id="+id);
//            System.out.println(base64QRCode);
        //转换为二维码图片
        MultipartFile multipartFile = Base64DecodeMultipartFile.base64ToMultipart(base64QRCode);
        //获取stream格式文件
        InputStream inputStream = multipartFile.getInputStream();

        //上传到oss
        String ext = "png";
        Date now = new Date();
        SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd");
        String newfilename = date.format(now) + "/";
        SimpleDateFormat time = new SimpleDateFormat("HHmmssSSS");
        newfilename += time.format(now);
        newfilename += "_" + new Random().nextInt(1000) + "." + ext;

        ossUtil.uploadFile2OSS(inputStream, newfilename);
        String url = "https://" + env.getProperty("oss.bucket") + "." + env.getProperty("oss.endpoint") + "/" + env.getProperty("oss.dir") + newfilename;
        return "/"+env.getProperty("oss.dir") + newfilename;

    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以通过以下步骤实现: 1. 引入依赖 在 pom.xml 文件中添加以下依赖: ``` <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.3.3</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.3.3</version> </dependency> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.10.2</version> </dependency> ``` 2. 生成二维码 在代码中使用以下方法生成二维码: ``` public static void generateQRCode(String content, String filePath) throws Exception { int width = 300; int height = 300; String format = "png"; Map<EncodeHintType, Object> hints = new HashMap<>(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints); Path path = FileSystems.getDefault().getPath(filePath); MatrixToImageWriter.writeToPath(bitMatrix, format, path); } ``` 其中,`content` 参数为生成二维码的内容,`filePath` 参数为生成的二维码保存的路径。 3. 上传OSS 使用以下代码将生成的二维码上传OSS: ``` public static void uploadFileToOSS(String endpoint, String accessKeyId, String accessKeySecret, String bucketName, String objectName, String filePath) { OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); try { ossClient.putObject(bucketName, objectName, new File(filePath)); } finally { ossClient.shutdown(); } } ``` 其中,`endpoint`、`accessKeyId`、`accessKeySecret`、`bucketName` 参数为 OSS 的配置信息,`objectName` 参数为上传OSS 后的文件名,`filePath` 参数为生成的二维码文件路径。 完整代码示例: ``` public static void generateQRCodeAndUploadToOSS(String content, String endpoint, String accessKeyId, String accessKeySecret, String bucketName, String objectName) throws Exception { int width = 300; int height = 300; String format = "png"; Map<EncodeHintType, Object> hints = new HashMap<>(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints); Path path = FileSystems.getDefault().getPath(objectName); MatrixToImageWriter.writeToPath(bitMatrix, format, path); OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); try { ossClient.putObject(bucketName, objectName, new File(objectName)); } finally { ossClient.shutdown(); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值