在Java中使用PrinterJob打印PDF文件

19

我在使用Java打印PDF文件时遇到了问题。这是我的代码:

PdfReader readFtp = new PdfReader();    // This class is used for reading a PDF file
PDDocument document = readFtp.readFTPFile(documentID);

printRequestAttributeSet.add(new PageRanges(1, 10));

job.setPageable(document);
job.print(printRequestAttributeSet);    // calling for print

document.close()


我使用 document.silentPrint(job);job.print(printRequestAttributeSet); - 它正常工作。如果我使用 document.silentPrint(job); - 我无法设置PrintRequestAttributeSet

请问有人可以告诉我如何设置PrintRequestAttributeSet吗?

6个回答

36

我的打印机不支持原生PDF打印。

我使用了开源库Apache PDFBox https://pdfbox.apache.org 来打印PDF。打印本身仍由Java的PrinterJob处理。

import java.awt.print.PrinterJob;
import java.io.File;

import javax.print.PrintService;
import javax.print.PrintServiceLookup;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.printing.PDFPageable;

public class PrintingExample {

    public static void main(String args[]) throws Exception {

        PDDocument document = PDDocument.load(new File("C:/temp/example.pdf"));

        PrintService myPrintService = findPrintService("My Windows printer Name");

        PrinterJob job = PrinterJob.getPrinterJob();
        job.setPageable(new PDFPageable(document));
        job.setPrintService(myPrintService);
        job.print();

    }       

    private static PrintService findPrintService(String printerName) {
        PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
        for (PrintService printService : printServices) {
            if (printService.getName().trim().equals(printerName)) {
                return printService;
            }
        }
        return null;
    }
}

3
最好关闭PDDocument,因此您需要一个try catch和finally,但总体来说还不错! - Petter Friberg
@RenRen,你能否通过这种方法自动获取打印状态? - Rose
@Rose 那时我没有使用打印状态。只是点火然后忘记。 - RenRen

21

我用以下方法成功地使用纯JRE打印了PDF:

public static void main(String[] args) throws PrintException, IOException {
    DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PAGEABLE;
    PrintRequestAttributeSet patts = new HashPrintRequestAttributeSet();
    patts.add(Sides.DUPLEX);
    PrintService[] ps = PrintServiceLookup.lookupPrintServices(flavor, patts);
    if (ps.length == 0) {
        throw new IllegalStateException("No Printer found");
    }
    System.out.println("Available printers: " + Arrays.asList(ps));

    PrintService myService = null;
    for (PrintService printService : ps) {
        if (printService.getName().equals("Your printer name")) {
            myService = printService;
            break;
        }
    }

    if (myService == null) {
        throw new IllegalStateException("Printer not found");
    }

    FileInputStream fis = new FileInputStream("C:/Users/John Doe/Desktop/SamplePDF.pdf");
    Doc pdfDoc = new SimpleDoc(fis, DocFlavor.INPUT_STREAM.AUTOSENSE, null);
    DocPrintJob printJob = myService.createPrintJob();
    printJob.print(pdfDoc, new HashPrintRequestAttributeSet());
    fis.close();        
}

2
这只能在Linux上运行,对吧?我相信在Windows上Java没有PDF渲染器,是吗? - Daniel
2
@Mirko Seifert 这段代码不起作用,我的打印机只打印出了无法识别的字符而不是我的 PDF 文档。 - whizzzkey
5
这段代码仅适用于可以自行解析PDF的打印机。我发现有些打印机可以做到这一点(例如某些惠普LaserJet型号),但我也遇到过一些打印机会打印出PDF文件的原始内容(作为文本)。在这种情况下,您需要将PDF转换为图像(例如使用Ghostview)。 - Mirko Seifert
2
尽管这篇回复是多年前发布的,但它仍然适用于今天,并为我节省了数小时的开发工作。感谢您,先生。无论您今天身在何处,都要感谢您! - eugene

3
以下是我使用的方法,可以打印多个PDF文档并显示打印对话框:
public void printPDF()
{
    PrinterJob printerJob = PrinterJob.getPrinterJob();

    PrintService printService;
    if(printerJob.printDialog())
    {
        printService = printerJob.getPrintService();
    }
    DocFlavor docType = DocFlavor.INPUT_STREAM.AUTOSENSE;

    for (//fetch documents to be printed)
    {
        DocPrintJob printJob = printService.createPrintJob();
        final byte[] byteStream = // fetch content in byte array;
            Doc documentToBePrinted = new SimpleDoc(new ByteArrayInputStream(byteStream), docType, null);
        printJob.print(documentToBePrinted, null);
    }
}

0
import java.awt.print.PrinterJob;
import java.io.File;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.printing.PDFPageable;

public class Main {

    public static void main(String[] args) throws Exception {

        String filename = "Path for PDF File"; 
        PDDocument document = PDDocument.load(new File (filename));

        //takes standard printer defined by OS
        PrintService myPrintService = PrintServiceLookup.lookupDefaultPrintService();
        myPrintService = findPrintService("Your Printer Name");
        PrinterJob job = PrinterJob.getPrinterJob();
        job.setPageable(new PDFPageable(document));
        job.setPrintService(myPrintService);
        job.print();

    }       

    private static PrintService findPrintService(String printerName) {
        PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
        for (PrintService printService : printServices) {
            if (printService.getName().trim().equals(printerName)) {
                return printService;
            }
        }
        return null;
    }

使用版本为2.0.4的Apache PDFBox。 如果使用Maven项目,请在XML文件中包含以下内容。
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.4</version>
</dependency>

2.0.4已经过时。 - Tilman Hausherr
@FrozenFlame 你能用这种方法自动获取打印状态吗? - Rose

0

尝试这段代码:

FileInputStream fis = new FileInputStream(“C:/mypdf.pdf”);
Doc pdfDoc = new SimpleDoc(fis, null, null);
DocPrintJob printJob = printService.createPrintJob();
printJob.print(pdfDoc, new HashPrintRequestAttributeSet());
fis.close();

您也可以按照这些步骤进行操作


1
他如何在没有DocFlavor的情况下打印PDF? - whizzzkey

-1

已弃用PDDocument的可分页实现,请改用PDPageable适配器类,并尝试使用setPrintable而非setPageable:

job.setPrintable(new PDPageable(document));

1
你好新用户!一个更好的示例,展示如何设置PageRanges,并提供对Javadoc API和版本的参考,将会很不错。 - Martin Serrano
PDFPageable 不是 PrintJob.setPrintable 方法的有效参数。 - JRSofty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接