条形码输出到pdf打印,封装工具类

mac2022-06-30  83

最近项目需要用到条形码,对于资产进行管理追踪,所以相应的就需要用到生成条形码的工具,在网上查找了相关资料之后,目前有几类产品,google 的zxing 、jbarcode、barcode4j-light 等,他们的区别我不再说,很多人有写,最终我选择的是jbarcode,选择这个是因为这个jar 可以生成中文文字等等,像一些博客所写的那样,开始写的时候,我也是想把文字直接绘制在条形码图片中,但是绘制之后发现效果不理想,调整输出条形码图片更改它的宽度等等都不太方便,所以最后还是选择直接绘制出条形码,不加任何文字,然后将绘制出的图片输出流直接写入pdf中,因为条形码打印需要特定的标签打印机,所以对于纸张的大小我们需要调整pdf页面的大小,而不是选择A4之类的纸张填写内容。所以,综合以上想法,我们的操作步骤是:

1、绘制条形码图片

2、将条形码图片输出流输入进pdf页面表格中

3、导出pdf

效果如下:

这里我们需要引入jbarcode.jar(绘制条形码),jbarcode在maven上没有,所以需要手动下载jar包,然后导入自己本地maven仓库引用。

导入:打开cmd ,输入以下命令即可,只需要更改你下载jbarcode后存放的地址即可

mvn install:install-file -Dfile="D:\Apache Maven\jbarcode-0.2.8.jar" -DgroupId=org.jbarcode -DartifactId=jbarcode -Dversion=0.2.8 -Dpackaging=jar

另外需要引入itext、itext-asian ,这个是操作pdf的

maven依赖:

<properties> <jbarcode.version>0.2.8</jbarcode.version> <iText.version>4.2.1</iText.version> <iTextAsian.version>5.2.0</iTextAsian.version> </properties> <!--引入条形码生成工具--> <dependency> <groupId>org.jbarcode</groupId> <artifactId>jbarcode</artifactId> <version>${jbarcode.version}</version> </dependency> <!-- pdf操作类--> <dependency> <groupId>com.lowagie</groupId> <artifactId>iText</artifactId> <version>${iText.version}</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>${iTextAsian.version}</version> </dependency>

关于如何操作pdf,网上有很多资料可以借鉴

http://www.anyrt.com/blog/list/itextpdf.html#1

不过需要注意:这里面有一个我遇到的很奇葩的bug

插图图片时:

PdfPCell cell = new PdfPCell(); byte[] bt = barCodeImgStream.toByteArray(); com.lowagie.text.Image image = Image.getInstance(bt); cell.setImage(image);

如果是先new一个单元格,然后装入图片,那么对于之前你设置的img图片的样式全部失效,需要注意

正确操作是:

byte[] bt = barCodeImgStream.toByteArray(); com.lowagie.text.Image image = Image.getInstance(bt); image.scaleAbsoluteHeight(imgHeight);//设置图片的高 image.scaleAbsoluteWidth(imgWidth);//设置图片的宽 //重点,必须将设置的图片在单元格new时放进单元格,而不是后续cell.setImg(),不然对于图片的设置会失效 PdfPCell cell = new PdfPCell(image);

直接在new单元格时将图片对象放进去,这样图片之前的样式设置才会生效,这个问题真的郁闷了我好久

 

直接上代码了:不废话了:想起来了,我用了lombox,小伙伴记得加上这个插件,这个插件是用来省去我们写get、set的

package com.xxx.common.utils; import com.lowagie.text.Image; import com.lowagie.text.Rectangle; import com.lowagie.text.*; import com.lowagie.text.pdf.BaseFont; import com.lowagie.text.pdf.PdfPCell; import com.lowagie.text.pdf.PdfPTable; import com.lowagie.text.pdf.PdfWriter; import com.xxx.common.core.domain.AjaxResult; import lombok.Data; import lombok.NoArgsConstructor; import org.jbarcode.JBarcode; import org.jbarcode.JBarcodeFactory; import org.jbarcode.encode.Code128Encoder; import org.jbarcode.paint.TextPainter; import org.jbarcode.util.ImageUtil; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import java.awt.*; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** *   *  * @projectName xxx *  * @title     BarCode2PdfUtil    *  * @package    com.xxx.common.utils   *  * @description    条形码序列号导出条形码至pdf *  * @author IT_CREAT      *  * @date  2019 2019/10/1 16:47   *  * @version V1.0.0  *   */ @Data @NoArgsConstructor public class BarCode2PdfUtil { // 设置条形码默认分辨率 public static final int BARCODE_DPI = ImageUtil.DEFAULT_DPI; /**条形码字节输出流*/ public List<ByteArrayOutputStream> barCodeOutPutStream = new ArrayList<>(); /**pdf操作文件*/ public Document pdfDocument = null; /**pdf文件输出流*/ public OutputStream pdfOs = null; /**pdf文件构造输出流*/ public PdfWriter pdfWriter = null; /** * 像素换算单位(1厘米约等于28.4像素) */ public static float pixelUnitForCm = 28.4f; /** * 像素换算单位(1mm约等于2.84像素) */ public static float pixelUnitForMm = 2.84F; /** * 设置一个标签纸大小的纸张 */ public static Rectangle LABLE_PAGE = new RectangleReadOnly(5.0f * pixelUnitForCm, 3.0f * pixelUnitForCm); /** * 字体大小 */ public float FONT_SIZE = 5F; /** * 声明图片固定高度12 */ public int imgHeight = 12; /** * 声明图片固定宽度110 */ public int imgWidth = 110; public static BarCode2PdfUtil create(){ return new BarCode2PdfUtil(); } public AjaxResult creatBarCode2Pdf(List<BarCodeData> barCodeDatas,String exportPath,String exportName){ if(CollectionUtils.isEmpty(barCodeDatas)){ return AjaxResult.error("条形码数据为空,装换失败"); } try { //判断文件夹存在不,不存在则创建 File file = new File(exportPath); if(!file.exists()){ file.mkdir(); } String outPath = exportPath + exportName; int index = 0; for (BarCodeData barCodeData:barCodeDatas){ if(!ObjectUtils.isEmpty(barCodeData)){ //得到二维码输出流 ByteArrayOutputStream byteArrayOutputStream = creatBarCodeImg(barCodeData.getBarCode()); if(index == 0){ pdfOs = new FileOutputStream(new File(outPath));//得到pdf文件输出流 createDocumentAndOpen(pdfOs);//创建pdf操作类,并打开 pdfDataWrite(barCodeData.getBarCode(),byteArrayOutputStream,barCodeData.getHeadShowData());//写入数据 }else { pdfDocument.newPage();//新建pdf页 pdfDataWrite(barCodeData.getBarCode(),byteArrayOutputStream,barCodeData.getHeadShowData());//写入数据 } index ++; } } close();//关闭各种流 return AjaxResult.success(outPath); }catch (Exception e){ e.printStackTrace(); return AjaxResult.error("转换条形码失败,多次尝试无果请联系管理员"); } } public void close() throws Exception { //关闭条形码输出流 if(!CollectionUtils.isEmpty(barCodeOutPutStream)){ for (ByteArrayOutputStream outputStream:barCodeOutPutStream) { outputStream.close(); } } //关闭pdf文件操作 if(!ObjectUtils.isEmpty(pdfDocument)){ pdfDocument.close(); } //关闭pdf输出流 if(!ObjectUtils.isEmpty(pdfOs)){ pdfOs.close(); } //关闭pdf构造出的输出流 if(!ObjectUtils.isEmpty(pdfWriter)){ pdfWriter.close(); } } /** * 构造一个pdf操作文件 */ public void createDocumentAndOpen(OutputStream pdfOs) throws Exception { if(pdfDocument == null){ //设置纸张为A4标签纸,左右上下边距全部为5 pdfDocument = new Document(LABLE_PAGE, 5, 5, 5, 5); // 构造好的pdf文件输出位置 pdfWriter = PdfWriter.getInstance(pdfDocument, pdfOs); //打开文件 pdfDocument.open(); } } /** * 对pdf进行数据写入操作 * @param barCode 条形码序列号 * @param barCodeImgStream 条形码输出流 * @param fontData 输出条形码头部显示数据 * @throws Exception 异常 */ public void pdfDataWrite(String barCode, ByteArrayOutputStream barCodeImgStream,Map<String, String> fontData) throws Exception { //itext在pdf中输入中文字体(中文楷体)时: BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); //创建表格,表格中是可以继续嵌入表格的,指定表格为1列 PdfPTable table = new PdfPTable(1);//1列 table.setHorizontalAlignment(1);//设置水平居中 table.setWidthPercentage(98);//设置table占页面比98% //创建装入头部中文信息的表格 PdfPTable tableTop = new PdfPTable(new float[]{30f,50f}); tableTop.setHorizontalAlignment(1);//设置水平居中 if (!ObjectUtils.isEmpty(fontData) && fontData.size() > 0) { for (String key : fontData.keySet()) { String value = fontData.get(key); //创建一个单元格 PdfPCell cell = new PdfPCell(); //插入key键值 Paragraph mess = new Paragraph(key, new com.lowagie.text.Font(bfChinese,FONT_SIZE)); mess.setAlignment(Element.ALIGN_CENTER);//设置碎屏剧中 cell.setPhrase(mess);//将字体装入单元格中 setPdfPCellStyle(cell);//统一设置单元格水平垂直居中 tableTop.addCell(cell); //插入key键value值 cell = new PdfPCell(); mess = new Paragraph(value, new com.lowagie.text.Font(bfChinese,FONT_SIZE)); cell.setPhrase(mess);//将字体装入单元格中 setPdfPCellStyle(cell);//统一设置单元格水平垂直居中 tableTop.addCell(cell); } } table.addCell(tableTop);//向全局表格中装入头部信息子表格 //创建底部装入条形码的表格 PdfPTable tableFoot = new PdfPTable(1); tableFoot.setHorizontalAlignment(1);//设置水平居中 if(!ObjectUtils.isEmpty(barCodeImgStream)){ //插入条形码图片 byte[] bt = barCodeImgStream.toByteArray(); com.lowagie.text.Image image = Image.getInstance(bt); image.scaleAbsoluteHeight(imgHeight);//设置图片的高 image.scaleAbsoluteWidth(imgWidth);//设置图片的宽 //重点,必须将设置的图片在单元格new时放进单元格,而不是后续cell.setImg(),不然对于图片的设置会失效 PdfPCell cell = new PdfPCell(image); setPdfPCellStyle(cell);//统一设置单元格水平垂直居中 cell.setMinimumHeight(20);//设置最小高度 cell.setBorderWidthBottom(0);//设置单元格底部边框为0 tableFoot.addCell(cell); //插入条形码号 Paragraph mess = new Paragraph(barCode, new com.lowagie.text.Font(bfChinese, 4)); mess.setAlignment(Element.ALIGN_CENTER); cell = new PdfPCell();//重新new一个单元格 cell.setBorderWidthTop(0);//设置单元格头部边框为0 cell.setPhrase(mess);//将字体装入单元格中 setPdfPCellStyle(cell);//统一设置单元格水平垂直居中 tableFoot.addCell(cell); } table.addCell(tableFoot);//将底部子表格装入大表格中 pdfDocument.add(table);//向页面中装入表格 } /** * 通用统一需要设置的单元格样式,垂直水平居中 * * @param cell1 */ public void setPdfPCellStyle(PdfPCell cell1) { //创建一个单元格 cell1.setUseAscender(true);//开启这个水平居中生效 cell1.setHorizontalAlignment(Element.ALIGN_CENTER); //水平居中 cell1.setVerticalAlignment(Element.ALIGN_MIDDLE); //垂直居中 cell1.setMinimumHeight(10);//设置最小高度 } //毫米转像素 public float mmTopx(float mm) { mm = (float) (mm * 2.84); return mm; } /** * 创建一个条形码图像 * @param barCode 传入条形码 * @throws Exception 异常 */ public ByteArrayOutputStream creatBarCodeImg(String barCode) throws Exception { BufferedImage image = creatBarCode().createBarcode(barCode);//得到一个图片操作对象 //传入图片对象,指定图片格式,设置图片像素,也就是设置宽高 ByteArrayOutputStream barCodeOutPut = new ByteArrayOutputStream();//创建一个字节输出流,让条形码输出到字节数组流中 barCodeOutPutStream.add(barCodeOutPut); ImageUtil.encodeAndWrite(image, ImageUtil.PNG,barCodeOutPut,BARCODE_DPI,BARCODE_DPI);//执行绘制图像,会进入重写的静态内部内方法中 return barCodeOutPut; } /**创建一个条形码实例*/ public JBarcode creatBarCode(){ // 生成code128 JBarcode jbc = JBarcodeFactory.getInstance().createCode128(); jbc.setEncoder(Code128Encoder.getInstance()); jbc.setTextPainter(CustomTextPainter.getInstance()); return jbc; } /** * 静态内部类 自定义的 TextPainter, * 允许定义字体,大小,文本等 参考底层实现:BaseLineTextPainter.getInstance() */ protected static class CustomTextPainter implements TextPainter { private static CustomTextPainter instance = new CustomTextPainter(); public static CustomTextPainter getInstance() { return instance; } public void paintText(BufferedImage barCodeImage, String text, int width) { Graphics g2d = barCodeImage.getGraphics(); g2d.fillRect(0, 0, barCodeImage.getWidth(), 0); g2d.fillRect(0, barCodeImage.getHeight(),barCodeImage.getWidth(),0); } } /** * 内部类,存放条形码所叙述句 */ @Data @NoArgsConstructor public static class BarCodeData{ /**条形码编号*/ private String barCode; /**头部显示数据*/ private Map<String,String> headShowData; } public static void main(String[] args) { //模拟第一条数据 HashMap<String, String> dataMap = new HashMap<>(); dataMap.put("商品名称","苹果笔记本电脑"); dataMap.put("联系人","张某某"); dataMap.put("联系电话","18888889489"); BarCodeData barCodeData = new BarCodeData(); barCodeData.setBarCode("1231225411"); barCodeData.setHeadShowData(dataMap); //模拟第二条数据 HashMap<String, String> dataMap1 = new HashMap<>(); dataMap1.put("商品名称","华为笔记本电脑"); dataMap1.put("联系人","李某某"); dataMap1.put("联系电话","17777779489"); BarCodeData barCodeData1 = new BarCodeData(); barCodeData1.setBarCode("1231225411"); barCodeData1.setHeadShowData(dataMap1); ArrayList<BarCodeData> list = new ArrayList<>(); list.add(barCodeData); list.add(barCodeData1); AjaxResult ajaxResult = BarCode2PdfUtil.create().creatBarCode2Pdf(list, "d:/file", "1.pdf"); System.out.println(ajaxResult); } }

这里有个封装的返回:(用过的细心地同学可以揣测出这是哪个框架)

package com.xxx.common.core.domain; import java.util.HashMap; import com.xxx.common.utils.StringUtils; /** * 操作消息提醒 * * @author xxx */ public class AjaxResult extends HashMap<String, Object> { private static final long serialVersionUID = 1L; /** 状态码 */ public static final String CODE_TAG = "code"; /** 返回内容 */ public static final String MSG_TAG = "msg"; /** 数据对象 */ public static final String DATA_TAG = "data"; /** * 状态类型 */ public enum Type { /** 成功 */ SUCCESS(0), /** 警告 */ WARN(301), /** 错误 */ ERROR(500); private final int value; Type(int value) { this.value = value; } public int value() { return this.value; } } /** * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。 */ public AjaxResult() { } /** * 初始化一个新创建的 AjaxResult 对象 * * @param type 状态类型 * @param msg 返回内容 */ public AjaxResult(Type type, String msg) { super.put(CODE_TAG, type.value); super.put(MSG_TAG, msg); } /** * 初始化一个新创建的 AjaxResult 对象 * * @param type 状态类型 * @param msg 返回内容 * @param data 数据对象 */ public AjaxResult(Type type, String msg, Object data) { super.put(CODE_TAG, type.value); super.put(MSG_TAG, msg); if (StringUtils.isNotNull(data)) { super.put(DATA_TAG, data); } } /** * 返回成功消息 * * @return 成功消息 */ public static AjaxResult success() { return AjaxResult.success("操作成功"); } /** * 返回成功数据 * * @return 成功消息 */ public static AjaxResult success(Object data) { return AjaxResult.success("操作成功", data); } /** * 返回成功消息 * * @param msg 返回内容 * @return 成功消息 */ public static AjaxResult success(String msg) { return AjaxResult.success(msg, null); } /** * 返回成功消息 * * @param msg 返回内容 * @param data 数据对象 * @return 成功消息 */ public static AjaxResult success(String msg, Object data) { return new AjaxResult(Type.SUCCESS, msg, data); } /** * 返回警告消息 * * @param msg 返回内容 * @return 警告消息 */ public static AjaxResult warn(String msg) { return AjaxResult.warn(msg, null); } /** * 返回警告消息 * * @param msg 返回内容 * @param data 数据对象 * @return 警告消息 */ public static AjaxResult warn(String msg, Object data) { return new AjaxResult(Type.WARN, msg, data); } /** * 返回错误消息 * * @return */ public static AjaxResult error() { return AjaxResult.error("操作失败"); } /** * 返回错误消息 * * @param msg 返回内容 * @return 警告消息 */ public static AjaxResult error(String msg) { return AjaxResult.error(msg, null); } /** * 返回错误消息 * * @param msg 返回内容 * @param data 数据对象 * @return 警告消息 */ public static AjaxResult error(String msg, Object data) { return new AjaxResult(Type.ERROR, msg, data); } }

 

最新回复(0)