本文参考https://blog.csdn.net/weixin_37848710/article/details/89522862
近期有个需求,需要生成打印面单的pdf文件
首先引入依赖
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<!--谷歌条形码依赖-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.2</version>
<exclusions>
<exclusion>
<artifactId>core</artifactId>
<groupId>com.google.zxing</groupId>
</exclusion>
</exclusions>
</dependency>
1、生成条形码的工具类
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.oned.Code128Writer;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ResourceUtils;
import shop.guangzhou.yunwuyou.utils.OssUtil;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* @description: 谷歌条形码打印
* @author: chenlilin
* @date: 2021-06-07 14:46
*/
public class GoogleBarCodeUtils {
/** 条形码宽度 */
private static final int WIDTH = 300;
/** 条形码高度 */
private static final int HEIGHT = 50;
/** 加文字 条形码 */
private static final int WORDHEIGHT = 75;
/**
* 设置 条形码参数
*/
private static Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>() {
private static final long serialVersionUID = 1L;
{
// 设置编码方式
put(EncodeHintType.CHARACTER_SET, "utf-8");
}
};
/**
* 生成 图片缓冲
* @author fxbin
* @param vaNumber VA 码
* @return 返回BufferedImage
*/
public static BufferedImage getBarCode(String vaNumber){
try {
Code128Writer writer = new Code128Writer();
// 编码内容, 编码类型, 宽度, 高度, 设置参数
BitMatrix bitMatrix = writer.encode(vaNumber, BarcodeFormat.CODE_128, WIDTH, HEIGHT, hints);
return MatrixToImageWriter.toBufferedImage(bitMatrix);
} catch (WriterException e) {
e.printStackTrace();
}
return null;
}
/**
* 把带logo的二维码下面加上文字
* @author fxbin
* @param image 条形码图片
* @param words 文字
* @return 返回BufferedImage
*/
public static BufferedImage insertWords(BufferedImage image, String words){
// 新的图片,把带logo的二维码下面加上文字
if (StringUtils.isNotEmpty(words)) {
BufferedImage outImage = new BufferedImage(WIDTH, WORDHEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = outImage.createGraphics();
// 抗锯齿
setGraphics2D(g2d);
// 设置白色
setColorWhite(g2d);
// 画条形码到新的面板
g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
// 画文字到新的面板
Color color=new Color(0, 0, 0);
g2d.setColor(color);
// 字体、字型、字号
g2d.setFont(new Font("微软雅黑", Font.PLAIN, 18));
//文字长度
int strWidth = g2d.getFontMetrics().stringWidth(words);
//总长度减去文字长度的一半 (居中显示)
int wordStartX=(WIDTH - strWidth) / 2;
//height + (outImage.getHeight() - height) / 2 + 12
int wordStartY=HEIGHT+20;
// 画文字
g2d.drawString(words, wordStartX, wordStartY);
g2d.dispose();
outImage.flush();
return outImage;
}
return null;
}
/**
* 设置 Graphics2D 属性 (抗锯齿)
* @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
*/
private static void setGraphics2D(Graphics2D g2d){
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
Stroke s = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
g2d.setStroke(s);
}
/**
* 设置背景为白色
* @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
*/
private static void setColorWhite(Graphics2D g2d){
g2d.setColor(Color.WHITE);
//填充整个屏幕
g2d.fillRect(0,0,600,600);
//设置笔刷
g2d.setColor(Color.BLACK);
}
/**
* 生成的图片保存到阿里云的oss(也可以保存到本地)
* @param word 条形码内容
* @return
* @throws IOException
*/
public static String createCode(String word) throws IOException {
BufferedImage image = insertWords(getBarCode(word), word);
File file = ResourceUtils.getFile("classpath:barcode.png");
ImageIO.write(image, "png", file);
// 如果图片是保存到本地,下面的代码就可以不用了
OssUtil ossUtil = OssUtil.getInstance();
InputStream fis = new FileInputStream(file);
String imagePath = "images/barcode.png";
ossUtil.postOssObject(imagePath,fis);
return OssUtil.OSSPATH + imagePath;
}
}
2、水印
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.GrayColor;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
/**
* 水印
*/
public class Watermark extends PdfPageEventHelper {
Font FONT = new Font(Font.FontFamily.HELVETICA, 30, Font.BOLD, new GrayColor(0.95f));
private String waterCont;//水印内容
public Watermark() {
}
public Watermark(String waterCont) {
this.waterCont = waterCont;
}
@Override
public void onEndPage(PdfWriter writer, Document document) {
for(int i=0 ; i<5; i++) {
for(int j=0; j<5; j++) {
ColumnText.showTextAligned(writer.getDirectContentUnder(),
Element.ALIGN_CENTER,
new Phrase(this.waterCont == null ? "yunwuj" : this.waterCont, FONT),
(50.5f+i*350),
(40.0f+j*150),
writer.getPageNumber() % 2 == 1 ? 45 : -45);
}
}
}
}
3、页码
package shop.guangzhou.yunwuyou.utils.pdf;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import java.io.IOException;
/**
* 页码
*/
public class MyHeaderFooter extends PdfPageEventHelper {
// 总页数
PdfTemplate totalPage;
Font hfFont;
{
try {
hfFont = new Font(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED), 8, Font.NORMAL);
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// 打开文档时,创建一个总页数的模版
@Override
public void onOpenDocument(PdfWriter writer, Document document) {
PdfContentByte cb =writer.getDirectContent();
totalPage = cb.createTemplate(30, 16);
}
// 一页加载完成触发,写入页眉和页脚
@Override
public void onEndPage(PdfWriter writer, Document document) {
PdfPTable table = new PdfPTable(3);
try {
table.setTotalWidth(PageSize.A4.getWidth() - 100);
table.setWidths(new int[] { 24, 24, 3});
table.setLockedWidth(true);
table.getDefaultCell().setFixedHeight(-10);
table.getDefaultCell().setBorder(Rectangle.BOTTOM);
table.addCell(new Paragraph("我是页眉/页脚", hfFont));// 可以直接使用addCell(str),不过不能指定字体,中文无法显示
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
table.addCell(new Paragraph("第" + writer.getPageNumber() + "页/", hfFont));
// 总页数
PdfPCell cell = new PdfPCell(Image.getInstance(totalPage));
cell.setBorder(Rectangle.BOTTOM);
table.addCell(cell);
// 将页眉写到document中,位置可以指定,指定到下面就是页脚
table.writeSelectedRows(0, -1, 50,PageSize.A4.getHeight() - 20, writer.getDirectContent());
} catch (Exception de) {
throw new ExceptionConverter(de);
}
}
// 全部完成后,将总页数的pdf模版写到指定位置
@Override
public void onCloseDocument(PdfWriter writer,Document document) {
String text = "总" + (writer.getPageNumber()) + "页";
ColumnText.showTextAligned(totalPage, Element.ALIGN_LEFT, new Paragraph(text,hfFont), 2, 2, 0);
}
}
文件二进制互转工具类
import org.springframework.util.FileCopyUtils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
/**
* 文件二进制互转工具类
* Author: momo
* Date: 2018/5/7
* Description:文件转为二进制
*/
public class BinUtil {
/**
* 文件转为二进制数组
* @param file
* @return
*/
public static byte[] fileToBinArray(File file){
try {
InputStream fis = new FileInputStream(file);
byte[] bytes = FileCopyUtils.copyToByteArray(fis);
return bytes;
}catch (Exception ex){
throw new RuntimeException("transform file into bin Array 出错",ex);
}
}
/**
* 文件转为二进制字符串
* @param file
* @return
*/
public static String fileToBinStr(File file){
try {
InputStream fis = new FileInputStream(file);
byte[] bytes = FileCopyUtils.copyToByteArray(fis);
return new String(bytes,"ISO-8859-1");
}catch (Exception ex){
throw new RuntimeException("transform file into bin String 出错",ex);
}
}
/**
* 二进制字符串转文件
* @param bin
* @param fileName
* @param parentPath
* @return
*/
public static File binToFile(String bin,String fileName,String parentPath){
try {
File fout = new File(parentPath,fileName);
fout.createNewFile();
byte[] bytes1 = bin.getBytes("ISO-8859-1");
FileCopyUtils.copy(bytes1,fout);
//FileOutputStream outs = new FileOutputStream(fout);
//outs.write(bytes1);
//outs.flush();
//outs.close();
return fout;
}catch (Exception ex){
throw new RuntimeException("transform bin into File 出错",ex);
}
}
/**
* 文件转为二进制数组
* 等价于fileToBin
* @param file
* @return
*/
public static byte[] getFileToByte(File file) {
byte[] by = new byte[(int) file.length()];
try {
InputStream is = new FileInputStream(file);
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
byte[] bb = new byte[2048];
int ch;
ch = is.read(bb);
while (ch != -1) {
bytestream.write(bb, 0, ch);
ch = is.read(bb);
}
by = bytestream.toByteArray();
} catch (Exception ex) {
throw new RuntimeException("transform file into bin Array 出错",ex);
}
return by;
}
}
4、生成pdf文件
package shop.guangzhou.yunwuyou.utils.pdf;
import com.itextpdf.text.*;
import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.*;
import java.io.File;
import java.io.FileOutputStream;
public class PdfReport {
// 定义全局的字体静态变量
private static Font titlefont;
private static Font headfont;
private static Font keyfont;
private static Font textfont;
// 最大宽度
private static int maxWidth = 1000;
// 静态代码块
static {
try {
// 不同字体(这里定义为同一种字体:包含不同字号、不同style)
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
titlefont = new Font(bfChinese, 8, Font.BOLD);
headfont = new Font(bfChinese, 8, Font.BOLD);
keyfont = new Font(bfChinese, 8, Font.BOLD);
textfont = new Font(bfChinese, 8, Font.NORMAL);
} catch (Exception e) {
e.printStackTrace();
}
}
// main测试
public static void main(String[] args) throws Exception {
try {
// 1.新建document对象
Document document = new Document(new RectangleReadOnly(283.5F, 283.5F), 10.0F, 10.0F, 10.0F, 10.0F);// 建立一个Document对象
// 2.建立一个书写器(Writer)与document对象关联
File file = new File("D:\\PDFDemo.pdf");
file.createNewFile();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
writer.setPageEvent(new Watermark("yunwuj"));// 水印
writer.setPageEvent(new MyHeaderFooter());// 页眉/页脚
// 3.打开文档
document.open();
document.addTitle("订单面单");// 标题
// 4.向文档中添加内容
new PdfReport().generatePDF(document);
// 5.关闭文档
document.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// 生成PDF文件
public void generatePDF(Document document) throws Exception {
// 表格
PdfPTable table = createTable(1);
table.addCell(createCell("寄件地址", textfont));
table.addCell(createCell("广州市", textfont,0,2));
table.addCell(createCell("收件地址", textfont));
table.addCell(createCell("NRT5-日本(FBA)\n" +
"Adds:埼玉県 Saitama川越 KawagoeAmazo\n" +
"n 川越FC 埼玉県川越市南台1-10-15 1-10-1\n" +
"5 Minamidai\n" +
"Postcode:〒350-1182\n", textfont,0,2));
//table.addCell(createCell("1", textfont));
PdfPCell cell = new PdfPCell(new Paragraph("运输"));
table.addCell(createCell("运输", textfont));
table.addCell(createCell("快递专线", textfont,0,2));
//table.addCell(createCell("1", textfont));
//生成条形码
String code = GoogleBarCodeUtils.createCode("16157894121545");
table.addCell(createCell("条形码", textfont));
// 如果生成的图片是保存在本地,可以将文件转化为二进制数组,通过二进制数组创建Image
Image image = Image.getInstance(code);
// image.reshapeImage();
image.scaleAbsolute(40,40);
table.addCell(image);
Image image1 = Image.getInstance("http://picture.yunwuyou.shop/images/QRCode/16185368110031386.jpg");
image.scaleAbsolute(50,50);
//image.scalePercent(5);
table.addCell(createCell("嘿嘿嘿嘿嘿", textfont));
document.add(table);
}
/**------------------------创建表格单元格的方法start----------------------------*/
/**
* 创建单元格(指定字体)
* @param value
* @param font
* @return
*/
public PdfPCell createCell(String value, Font font) {
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_LEFT);
cell.setHorizontalAlignment(Element.ALIGN_LEFT);
cell.setPhrase(new Phrase(value, font));
return cell;
}
/**
* 创建单元格(指定字体、水平..)
* @param value
* @param font
* @param align
* @return
*/
public PdfPCell createCell(String value, Font font, int align) {
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_LEFT);
cell.setHorizontalAlignment(align);
cell.setPhrase(new Phrase(value, font));
return cell;
}
/**
* 创建单元格(指定字体、水平居..、单元格跨x列合并)
* @param value
* @param font
* @param align
* @param colspan
* @return
*/
public PdfPCell createCell(String value, Font font, int align, int colspan) {
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_LEFT);
cell.setHorizontalAlignment(align);
cell.setColspan(colspan);
cell.setPhrase(new Phrase(value, font));
return cell;
}
/**
* 创建单元格(指定字体、水平居..、单元格跨x列合并、设置单元格内边距)
* @param value
* @param font
* @param align
* @param colspan
* @param boderFlag
* @return
*/
public PdfPCell createCell(String value, Font font, int align, int colspan, boolean boderFlag) {
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_LEFT);
cell.setHorizontalAlignment(align);
cell.setColspan(colspan);
cell.setPhrase(new Phrase(value, font));
cell.setPadding(3.0f);
if (!boderFlag) {
cell.setBorder(0);
cell.setPaddingTop(15.0f);
cell.setPaddingBottom(8.0f);
} else if (boderFlag) {
cell.setBorder(0);
cell.setPaddingTop(0.0f);
cell.setPaddingBottom(15.0f);
}
return cell;
}
/**
* 创建单元格(指定字体、水平..、边框宽度:0表示无边框、内边距)
* @param value
* @param font
* @param align
* @param borderWidth
* @param paddingSize
* @param flag
* @return
*/
public PdfPCell createCell(String value, Font font, int align, float[] borderWidth, float[] paddingSize, boolean flag) {
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_LEFT);
cell.setHorizontalAlignment(align);
cell.setPhrase(new Phrase(value, font));
cell.setBorderWidthLeft(borderWidth[0]);
cell.setBorderWidthRight(borderWidth[1]);
cell.setBorderWidthTop(borderWidth[2]);
cell.setBorderWidthBottom(borderWidth[3]);
cell.setPaddingTop(paddingSize[0]);
cell.setPaddingBottom(paddingSize[1]);
if (flag) {
cell.setColspan(2);
}
return cell;
}
/**
* 创建默认列宽,指定列数、水平(1居中、2右、0左)的表格
* @param align 对齐模式(0左、1居中、2右)
* @return
*/
public PdfPTable createTable(int align) {
//三列列宽不同若果是浮点数需要加f
float[] widths = new float[] { 80, 410, 410};
PdfPTable table = new PdfPTable(widths);
try {
table.setTotalWidth(maxWidth);
//table.setLockedWidth(true);
table.setHorizontalAlignment(align);
table.getDefaultCell().setBorder(1);
} catch (Exception e) {
e.printStackTrace();
}
return table;
}
}
测试生成的文件如下:
那个二维码的图片还有点问题,遮住了下边框,还在调试,如果有知道怎么解决的大佬,恳请告诉我
今天的文章itextpdf生成pdf文件(含图片)分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/31953.html