PDFBox 打印带背景的文件速度慢
打印慢的原因
java的RasterPrinterJob会执行很多次printPage方法
他应该是按块填充的, 如果页面元素非常复杂, 那么printPage方法可能会执行十几次.
而如果你用了如下代码中流式打印的方式, 每页pdf单独实现Printable接口, 重写print方法.
private static class FinePrintableDemo implements Printable { public FinePrintableDemo(PDDocument document, int index) {
this.index = index;
this.printable = new PDFPrintable(document);
} private int index;
private PDFPrintable printable; @Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
long start1 = System.currentTimeMillis();
int res = printable.print(graphics, pageFormat, index);
long end1 = System.currentTimeMillis();
System.out.println("打印第 " + (index + 1) + "页 耗时 : " + (end1 - start1) +" 毫秒 "); return res;
}
}
会发现print方法同样被执行了十几次, 造成一个带背景的pdf打印耗时十几秒.
慢在哪
慢在每次都重复解析同一页pdf内容. 打了断点后会发现每页都在PDFStreamEngine.processStream
public void renderPageToGraphics(int pageIndex, Graphics2D graphics, float scale) throws IOException {
PDPage page = this.document.getPage(pageIndex);
this.transform(graphics, page, scale);
PDRectangle cropBox = page.getCropBox();
graphics.clearRect(0, 0, (int)cropBox.getWidth(), (int)cropBox.getHeight());
PageDrawerParameters parameters = new PageDrawerParameters(this, page);
PageDrawer drawer = this.createPageDrawer(parameters);
drawer.drawPage(graphics, cropBox);
}
这个方法每次都会消耗1s左右.
怎么解决
最好的方式自然是改pdfbox源码, 不用每次都重新生成解析pdf文件. 不过那样稍微有点麻烦.
还有个更简单的方式, 既然pdf会被反复解析, 那么我们在print之前把pdf转成图片, 然后直接打印图片即可.
即使RasterPrinterJob.printPage执行十几次, 也不过在绘制Image, 时间会非常短.
因此我们将代码稍微改造下, 在printable.print方法中直接打印图片.
private static class FinePrintableDemo implements Printable { private BufferedImage image; public FinePrintableDemo(PDDocument document, int index) {
// 获取pdf文件, 将其中指定的页面转成图片.
PDFRenderer renderer = new PDFRenderer(document);
try {
this.image = renderer.renderImage(index, 1, ImageType.RGB);
} catch (IOException e) {
e.printStackTrace();
} } @Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
long start1 = System.currentTimeMillis();
Graphics2D g2d = (Graphics2D) graphics.create();
Paint paint = g2d.getPaint(); int width = this.image.getWidth();
int height = this.image.getHeight(); Shape shape = new Rectangle2D.Double(0, 0, width, height);
g2d.setPaint(createPaint(shape, StableUtils.isNotSupportARGB(g2d), image, width, height));
g2d.fill(shape);
g2d.setPaint(paint);
g2d.dispose();
long end1 = System.currentTimeMillis();
System.out.println("打印第 " + (pageIndex + 1) + "页 耗时 : " + (end1 - start1) +" 毫秒 ");
return Printable.PAGE_EXISTS;
} private Paint createPaint(Shape shape, boolean isNotSupportARGB, BufferedImage image, int width, int height) {
Rectangle2D rec2D = shape.getBounds2D();
if ((int) rec2D.getWidth() <= 0) {
rec2D.setRect(rec2D.getX(), rec2D.getY(), rec2D.getWidth() + 40, rec2D.getHeight());
}
if ((int) rec2D.getHeight() <= 0) {
rec2D.setRect(rec2D.getX(), rec2D.getY(), rec2D.getWidth(), rec2D.getHeight() + 40);
}
BufferedImage buffered = new BufferedImage((int) rec2D.getWidth(), (int) rec2D.getHeight(), isNotSupportARGB ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = buffered.createGraphics();
GraphHelper.paintImage(g2, (int) rec2D.getWidth(), (int) rec2D.getHeight(), image,
Constants.IMAGE_CENTER , Constants.LEFT, Constants.TOP, width, height, isNotSupportARGB); g2.dispose(); return new TexturePaint(buffered, rec2D);
}
}
这一次print方法同样被执行了十几次, 但是每次也就十几毫秒, 文件很快就被打印出来了.
完整代码如下
package com.fr.base; import com.fr.stable.Constants;
import com.fr.stable.StableUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer; import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.TexturePaint;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; public class doStreamImagePrint { public static void main(String[] args) throws IOException, PrinterException {
PrinterJob job = PrinterJob.getPrinterJob(); int width = 595;
int height = 842;
int marginLeft = 0;
int marginRight = 0;
int marginTop = 0;
int marginBottom = 0; Paper paper = new Paper();
paper.setSize(width, height);
// 设置边距
paper.setImageableArea(marginLeft, marginRight, width - (marginLeft + marginRight), height - (marginTop + marginBottom));
// 自定义页面设置
PageFormat pageFormat = new PageFormat();
// 设置页面横纵向
pageFormat.setOrientation(PageFormat.PORTRAIT);
pageFormat.setPaper(paper); // 构建一个有size的空book, book里都是引用. 实际打印哪一页就从远程获取哪一页
Book printBook = new Book();
// 真正打印的时候, 每页的printable都new pdfprintable.print();
printBook.append(convertPDFToPrint("D:\\bg.pdf", 0), pageFormat);
printBook.append(convertPDFToPrint("D:\\bg.pdf", 0), pageFormat); job.setPageable(printBook);
job.print();
} private static FinePrintableDemo convertPDFToPrint(String path, int index) throws IOException {
InputStream in = new FileInputStream(path);
PDDocument document = PDDocument.load(in);
return new FinePrintableDemo(document, index);
} private static class FinePrintableDemo implements Printable { private BufferedImage image; public FinePrintableDemo(PDDocument document, int index) {
// 获取pdf文件, 将其中指定的页面转成图片.
PDFRenderer renderer = new PDFRenderer(document);
try {
this.image = renderer.renderImage(index, 1, ImageType.RGB);
} catch (IOException e) {
e.printStackTrace();
} } @Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
long start1 = System.currentTimeMillis();
Graphics2D g2d = (Graphics2D) graphics.create();
Paint paint = g2d.getPaint(); int width = this.image.getWidth();
int height = this.image.getHeight(); Shape shape = new Rectangle2D.Double(0, 0, width, height);
g2d.setPaint(createPaint(shape, StableUtils.isNotSupportARGB(g2d), image, width, height));
g2d.fill(shape);
g2d.setPaint(paint);
g2d.dispose();
long end1 = System.currentTimeMillis();
System.out.println("打印第 " + (pageIndex + 1) + "页 耗时 : " + (end1 - start1) +" 毫秒 ");
return Printable.PAGE_EXISTS;
} private Paint createPaint(Shape shape, boolean isNotSupportARGB, BufferedImage image, int width, int height) {
Rectangle2D rec2D = shape.getBounds2D();
if ((int) rec2D.getWidth() <= 0) {
rec2D.setRect(rec2D.getX(), rec2D.getY(), rec2D.getWidth() + 40, rec2D.getHeight());
}
if ((int) rec2D.getHeight() <= 0) {
rec2D.setRect(rec2D.getX(), rec2D.getY(), rec2D.getWidth(), rec2D.getHeight() + 40);
}
BufferedImage buffered = new BufferedImage((int) rec2D.getWidth(), (int) rec2D.getHeight(), isNotSupportARGB ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = buffered.createGraphics();
GraphHelper.paintImage(g2, (int) rec2D.getWidth(), (int) rec2D.getHeight(), image,
Constants.IMAGE_CENTER , Constants.LEFT, Constants.TOP, width, height, isNotSupportARGB); g2.dispose(); return new TexturePaint(buffered, rec2D);
}
} }
PDFBox 打印带背景的文件速度慢的更多相关文章
- Lodop如何设置预览后导出带背景的图,打印不带背景图
Lodop中的ADD_PRINT_SETUP_BKIMG,可以加载上背景图,该背景图在预览的时候可以显示也可以不显示,打印可以打印出来也可以不打印出来.一般套打,都是不打印背景图的,比如一些快递的快递 ...
- 导出不带.svn的文件夹或者是不含.class的文件
转载自:http://blog.csdn.net/z278718149/article/details/21537395 如何导出不带.svn的文件夹或者是不含.class的文件 在工作环境中,有的时 ...
- 如何导出不带.svn的文件夹
在工作环境中,有的时候需要将本地SVN服务器中的文件导出来,提交到另一个SVN服务器中去(比如做现场开发时,由于外网速度慢,项目组内部往往使用一个SVN服务器,但又同时又需要公司统一管理,定期提交到公 ...
- Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录)
Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录) 作者:王可利(Star·星星) 效果图: 代码如下: class Star8 { public static void m ...
- git bash中带空格的文件夹以及文件的处理
空格用'\ '表示,输入的时候,是不需要单引号的 total 338drwxr-xr-x 9 Administ Administ 4096 Aug 24 23:53 HDTHelperdrwxr-xr ...
- Python_服务器与多客户端通信、UDP协议、pycharm打印带颜色输出、时间同步的机制
1.服务器与多客户端通信 import socket # 创建tcp socket的套接字 sk = socket.socket() # bind sk.bind(('127.0.0.1',8080) ...
- Lodop打印控件不打印css背景图怎么办
background:url()这是css背景图,http协议会按异步方式下载背景图,所以很容易等不到下载完毕就开始打印了,故lodop不打印css背景图.Lodop不打印css背景图,但是有其他方法 ...
- linux下怎么删除名称带空格的文件
linux下怎么删除名称带空格的文件-rm 'mysql bin.000005' 用引号把文件名括起来 某些情况下会出现名称带空格的文件, 如果想要删除的话,直接用rm mysql bin.00000 ...
- phpqrcode 分别生成普通、带logo、带背景带logo二维码
前提:下载好 phpqrcode 类库 1.生成普通二维码 //引入类库 include('phpqrcode/phpqrcode.php'); //二维码里面的链接地址 $url="htt ...
随机推荐
- 理解typename的两个含义
理解typename的两个含义 问题:在下面的 template declarations(模板声明)中 class 和 typename 有什么不同? template<class T> ...
- HDU1792A New Change Problem(GCD规律推导)
A New Change Problem Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- LR多分类推广 - Softmax回归*
LR是一个传统的二分类模型,它也可以用于多分类任务,其基本思想是:将多分类任务拆分成若干个二分类任务,然后对每个二分类任务训练一个模型,最后将多个模型的结果进行集成以获得最终的分类结果.一般来说,可以 ...
- outline
a标签 两种button按钮 默认带有一个虚线 outline 当他们被单击 和 激活以后 outline和border 很类似 ,但是有不同 1.outline 不能针对特定的边赋值 ,也就 ...
- Problem B: 时间和日期类(III)
Problem B: 时间和日期类(III) Time Limit: 4 Sec Memory Limit: 128 MBSubmit: 2889 Solved: 1732[Submit][Sta ...
- C++分布式实时应用框架 (Cpp Distributed Real-time Application Framework)----(一):整体介绍
C++分布式实时应用框架 (Cpp Distributed Real-time Application Framework) 在现今软件系统纷纷"云化"的浪潮下,各种支持" ...
- Spring Security Ajax 被拦截
背景是项目中使用Spring Security 进行安全控制 再使用Ajax的时候会报 403(ajax get 方式是没问题的 post 的时候会报) Spring Security 原本是 防止 ...
- Maven 编译错误 Dynamic Web Module 3.0 requires Java 1.6 or newer 解决方案
Eclipse Maven 开发一个 jee 项目时,编译时遇到以下错误:Description Resource Path Location TypeDynamic Web Module 3.0 r ...
- httpwebrequest 用GET方法时报无法发送具有此谓词类型的内容正文
如下一段小程序,运行结果报无法发送具有此谓词类型的内容正文的错误,其实原因很简单,因为用的是GET的方式进行提交,而GetRequestStream()是用来在post提交的时候写post的内容的流, ...
- 【转】使用PowerDesigner的建模创建升级管理数据库
使用PowerDesigner的建模创建升级管理数据库 PowerDesigner是一种著名的CASE建摸工具,最开始为数据库建模设计,即物理模型(Physical Data Model)用于生成数据 ...