JAVA生成条码或二维码存储到PDF文件中并输出到前端页面展示

一、业务需求

        为流水号生成条码或二维码,批量存放到一个pdf文件中,并在前端显示。

二、思路

        1.获取需要生成条码或二维码的数据
        2.生成条码或二维码
        3.存放到pdf文件中
        4.输出到前端页面

三、参考资料

https://blog.csdn.net/fanghuainihao/article/details/99547932  (主要采用方法三)

https://www.jb51.net/article/183515.htm

四、实现

1.引入pom

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
 
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext7-core</artifactId>
            <version>7.1.7</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-util</artifactId>
            <version>1.11</version>
        </dependency>
 
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-transcoder</artifactId>
            <version>1.11</version>
        </dependency>
 
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>fop</artifactId>
            <version>2.3</version>
        </dependency>

2.生成带文字的二维码

将生成二维码并放入PDF文件的方法写成工具类:


import com.QRCodeEntity;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BarcodeQRCode;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.FileOutputStream;
/**
 * 生成可带文字的二维码工具类
 *
 */
public class QRCodeToPDF {

    public void createPDF(QRCodeEntity qrCodeEntity) throws DocumentException
    {
        FileOutputStream out = qrCodeEntity.getFileOutputStream();
        Document document = new Document();
        // 虽然没被使用,但是如果不写的话传到前端的文件会无法加载
        PdfWriter pdfWriter = PdfWriter.getInstance(document, out);
        document.open();
        int size = qrCodeEntity.getCodelist().size();
        for (int i = 0; i < size; i++)
        {
            document.add(new Paragraph(qrCodeEntity.getCodelist().get(i).getCodeTitle()));
            BarcodeQRCode qrcode = new BarcodeQRCode(qrCodeEntity.getCodelist().get(i).getCodeScan(),
                    qrCodeEntity.getCodeWidth(),
                    qrCodeEntity.getCodeHeight(),
                    null);
            Image qrcodeImage = qrcode.getImage();
            qrcodeImage.setAbsolutePosition(qrCodeEntity.getAbsoluteX(),qrCodeEntity.getAbsoluteY());
            document.add(qrcodeImage);
        }
        document.close();
    }
}

该工具类所需参数类:

package com.entity;

import lombok.Data;

import java.io.FileOutputStream;
import java.util.List;

/**
 * 生成可带文字的二维码工具类参数
 *
 */
@Data
public class QRCodeEntity {

    // 文件输入流
    private FileOutputStream fileOutputStream;

    // 二维码宽度
    private int codeWidth;

    // 二维码高度
    private int codeHeight;

    // 二维码在pdf页中绝对位置
    private int absoluteX;

    // 二维码在pdf页中绝对位置
    private int absoluteY;

    // 存放二维码扫描内容和显示内容的list
    private List<CodeList> codelist;


    public QRCodeEntity(FileOutputStream fileOutputStream, int codeWidth, int codeHeight, int absoluteX, int absoluteY, List<CodeList> codelist) {
        this.fileOutputStream = fileOutputStream;
        this.codeWidth = codeWidth;
        this.codeHeight = codeHeight;
        this.absoluteX = absoluteX;
        this.absoluteY = absoluteY;
        this.codelist = codelist;
    }
}
package com.entity;

import lombok.Data;

/**
 * 带文字二维码
 *
 */
@Data
public class CodeList {

    // 二维码扫描内容
    private String codeScan;

    // 二维码展示内容
    private String codeTitle;
}

实现效果:

优点:不仅可以生成二维码,还可以将二维码信息,或你想展示的内容输出到pdf文件中。

缺点:改变pdf每页大小不便捷,只能通过document.setPageSize(PageSize.A4);这种方式去设置已经封装好了的页面大小。

3.生成条码或二维码

将生成方法写成工具类:

package com.utils;

import com.BarCodeEntity;
import com.itextpdf.barcodes.Barcode128;
import com.itextpdf.barcodes.BarcodeQRCode;
import com.itextpdf.barcodes.qrcode.EncodeHintType;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;

import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

public class BarCodeToPDF {

    public void createPDF(BarCodeEntity barCodeEntity) {
        try
        {
            OutputStream os = barCodeEntity.getFileOutputStream();
            PdfDocument pdfDoc = new PdfDocument(new PdfWriter(os));
            int size = barCodeEntity.getBarCodeList().size();
            for (int i = 0; i < size; i++)
            {
                PdfPage pdfPage = pdfDoc.addNewPage(new PageSize(barCodeEntity.getPageWidth(), barCodeEntity.getPageHeight()));
                PdfCanvas canvas = new PdfCanvas(pdfPage);
                PdfFormXObject pdfFormXObject;
                if (barCodeEntity.getType() == 1) {
                    pdfFormXObject = createBarcode1D(barCodeEntity.getBarCodeList().get(i),
                            pdfDoc,barCodeEntity.getCodeSize(),barCodeEntity.getCodeHeight(),barCodeEntity.getCodeBaseline());
                } else {
                    pdfFormXObject = createBarcode2D(barCodeEntity.getBarCodeList().get(i), pdfDoc,barCodeEntity.getModuleSize());
                }
                canvas.addXObject(pdfFormXObject, barCodeEntity.getAbsoluteX(), barCodeEntity.getAbsoluteY(), barCodeEntity.getWidth());
            }

            pdfDoc.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public static PdfFormXObject createBarcode1D(String code, PdfDocument pdfDoc,int codeSize,int codeHeight,int codeBaseline)
    {
        Barcode128 code128 = new Barcode128(pdfDoc);
        code128.setSize(codeSize);
        code128.setBarHeight(codeHeight);
        code128.setCode(code);
        code128.setBaseline(codeBaseline);
        code128.setCodeType(Barcode128.CODE128);
        PdfFormXObject pdfFormXObject = code128.createFormXObject(ColorConstants.BLACK,
                ColorConstants.BLACK,
                pdfDoc);

        return pdfFormXObject;
    }

    public static PdfFormXObject createBarcode2D(String code, PdfDocument pdfDoc, int moduleSize)
    {
        BarcodeQRCode qrcode = new BarcodeQRCode(code);
        Map<EncodeHintType, Object> HINTS = new HashMap<EncodeHintType, Object>();
        HINTS.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        qrcode.setHints(HINTS);
        PdfFormXObject pdfFormXObject = qrcode.createFormXObject(ColorConstants.BLACK,
                moduleSize,
                pdfDoc);

        return pdfFormXObject;
    }
}

这里提供了createBarcode1D和createBarcode2D两个方法,可以根据参数中的type字段来区分生成的是条形码还是二维码。

该工具类所需参数类:

package com.glob.core.entity;

import lombok.Data;

import java.io.FileOutputStream;
import java.util.List;

/**
 * 生成条码和二维码工具类参数
 *
 */
@Data
public class BarCodeEntity {

    // 文件输入流
    private FileOutputStream fileOutputStream;

    // 条码内容
    private List<String> barCodeList;

    // 页面宽度
    private int pageWidth;

    // 页面高度
    private int pageHeight;

    // 条码下文字大小
    private int codeSize;

    // 条码高度
    private int codeHeight;

    // 条码与文字之间的距离
    private int codeBaseline;

    // 二维码大小
    private int moduleSize;

    // 码在pdf页中绝对位置
    private int absoluteX;

    // 码在pdf页中绝对位置
    private int absoluteY;

    // 条码在pdf中的大小
    private float width;

    // 打印类型   1:条码  2:二维码
    private int type;
}

要注意,codeSize  codeHeight  codeBaseline为生成条形码时所需的参数

              moduleSize是生成二维码时所需的参数

生成条码实现效果:

生成二维码实现效果:

 优点:可以灵活调整pdf文件页面大小,并且时直接在pdf文件中画条码,比较高效

 缺点:我在所使用的包内并没有看到如何在二维码下面显示相关内容,后续又研究出方法一来显示文字+二维码,所以就没有深入研究。

4.前后端调用

使用的是spring boot + vue的前后端,以方法1举例说明

后端代码:

/**
     * 打印pdf文件
     * @param response
     * @param mo
     * @throws IOException
     * @throws DocumentException
     */
    @PostMapping("/pdf")
    @RequiresPermissions("produce:product:pdf")
    public void getPdf(HttpServletResponse response, ProductMo mo) throws IOException, DocumentException {
        // 生成带文字描述的二维码pdf文件
        SimpleDateFormat sdf =   new SimpleDateFormat( "yyyyMMddHHmmss" );
        String name = "productIdToPDF" + sdf.format(new Date());
        FileOutputStream out = new FileOutputStream(name);
        List<CodeList> codeLists = null;
        // 判断是否选中行
        if (StringUtils.isNotBlank(mo.getProductList())) {
            String[] productList = mo.getProductList().split(",");
            codeLists = 数据库查询结果;
        } else {
            codeLists = 数据库查询结果;
        }
        // 调用pdf文件生成工具类
        QRCodeEntity qrCodeEntity = new QRCodeEntity(
                out, 300, 300, 10, 300, codeLists);
        QRCodeToPDF qrCodeToPDF = new QRCodeToPDF();
        qrCodeToPDF.createPDF(qrCodeEntity);
        OutputStream toClient = null;
        try {
            FileInputStream hFile = new FileInputStream(name); // 以byte流的方式打开文件
            int i = hFile.available(); // 得到文件大小
            byte data[] = new byte[i];
            hFile.read(data); // 读数据
            hFile.close();
            response.reset();
            response.resetBuffer();
            response.setContentType("application/pdf;charset-UTF-8"); // 设置返回的文件类型
            toClient = response.getOutputStream(); // 得到向客户端输出二进制数据的对象
            toClient.write(data); // 输出数据
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                toClient.flush();
                toClient.close();
            } catch (Exception ex) {
            }
        }

    }

前端代码:

handleExport () {
      var message = null;
      if (this.ids.length === 0) {
        this.queryParams.productList = []
        message = '当前未选中数据,确认打印"' + this.queryParams.executeCod + '"下所有的流水号?';
      } else {
        this.queryParams.productList = JSON.stringify(this.ids)
        this.queryParams.productList = this.queryParams.productList.replace("[", "");
        this.queryParams.productList = this.queryParams.productList.replace("]", "");
        message = '确认打印所选流水号?'
      }
      this.$confirm(message, "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        this.exportLoading = true;
        console.log(this.queryParams)
        return getPdf(this.queryParams);
      }).then(response => {
        this.getList();
        let blob = new Blob([response], { type: "application/pdf;charset-UTF-8" });
        let objectUrl = URL.createObjectURL(blob);
        // window.location.href = objectUrl;
        window.open(objectUrl);
        this.exportLoading = false;
      }).catch(() => { });
    }

引入api文件:

import request from '@/utils/request'

// 获取pdf
export function getPdf (query) {
  return request({
    url: '请求地址',
    method: 'post',
    params: query,
    responseType: 'arraybuffer'
  })
}

要注意 responseType必须要设置成 'arraybuffer',不然后端返回的pdf文件会变成空白页。

补充:方法三效果图中所用参数

        条形码参数

barCodeEntity.setType(1); // 生成条码
barCodeEntity.setCodeSize(13); 
barCodeEntity.setCodeHeight(70); 
barCodeEntity.setCodeBaseline(20);
barCodeEntity.setPageWidth(300);
barCodeEntity.setPageHeight(200);
barCodeEntity.setModuleSize(8);
barCodeEntity.setAbsoluteX(55);
barCodeEntity.setAbsoluteY(10);
barCodeEntity.setWidth(0.85f);

        二维码参数

barCodeEntity.setType(2); // 生成二维码
barCodeEntity.setModuleSize(8);
barCodeEntity.setPageWidth(300);
barCodeEntity.setPageHeight(200);
barCodeEntity.setModuleSize(8);
barCodeEntity.setAbsoluteX(55);
barCodeEntity.setAbsoluteY(10);
barCodeEntity.setWidth(0.85f);
  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值