为流水号生成条码或二维码,批量存放到一个pdf文件中,并在前端显示。
1.获取需要生成条码或二维码的数据
2.生成条码或二维码
3.存放到pdf文件中
4.输出到前端页面
https://blog.csdn.net/fanghuainihao/article/details/99547932 (主要采用方法三)
https://www.jb51.net/article/183515.htm
com.itextpdf
itextpdf
5.5.13
com.itextpdf
itext-asian
5.2.0
com.itextpdf
itext7-core
7.1.7
pom
org.apache.xmlgraphics
batik-util
1.11
org.apache.xmlgraphics
batik-transcoder
1.11
org.apache.xmlgraphics
fop
2.3
将生成二维码并放入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;
public QRCodeEntity(FileOutputStream fileOutputStream, int codeWidth, int codeHeight, int absoluteX, int absoluteY, List 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);这种方式去设置已经封装好了的页面大小。
将生成方法写成工具类:
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 HINTS = new HashMap();
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 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文件中画条码,比较高效。
缺点:我在所使用的包内并没有看到如何在二维码下面显示相关内容,后续又研究出方法一来显示文字+二维码,所以就没有深入研究。
使用的是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 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);