如何在java中用javascript来打印pdf

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在java中用javascript来打印pdf相关的知识,希望对你有一定的参考价值。

参考技术A   纯Java的解决方案:
  我们首先想到的自然就是JDK1.4提供的JPS(Java Printing Service)啦,不过,这东西虽然说支持PDF的Flavor,但是,不管是个人实验还是网上他人的评论,好像根本就是useless,可能如果说你 的打印机Driver支持PDF的Flavor的话,JPS会检测到你的driver的这个特性,能够成功的打印PDF文档出来,但是,大部分情况下,这 种情形是不成立的,故此JPS死路一条啦!
  让我们看看PDF的老家Adobe那里有没有什么法宝,我们发现一个Viewer Bean的组件,说是可以将PDF以Bean组件的方式潜入到Swing中,哇,太爽了,不过慢着,协议上说不提供任何支持,也不保证不出任何问题,管那 么些,试过再说,一实验才知道,靠,Exception频发,而且这个组件较为陈旧,还是扔一边吧!
  还有一个PDFBox,Open Source的,不过对中文支持不好,而且好像开发进度也不是很好,没有发布一个正式的版本,基本上不能用于生产环境;
  最后,求助于Commercial的产品吧,实验了一下ActiveTree的JPrint,感觉不错,完全可以胜任我们的需求而且恰到好处,不过授权费 很贵,Email问过之后的答复是2000USD的最低购买,呵呵,虽然日本人很有钱,但也心疼这个银子啊,所以最终也得作罢!(ActiveTree的 授权其实挺令我ft的,他其实在2003年的时候是可以免费使用的,但之后就变卦了,呵呵,当时记得我还给提过一些bug之类,算了,人家做出这个东西也 不容易)
  其他商业产品也是价格不菲,所以,基本上纯Java的solution到这里就否决了,让我们看Java-Com的解决方案吧!

  Java-Com 的解决方案:
  在前一条路走不通之后,我痛定思痛,决定转向自己不熟悉的领域,ms的领地,我打算从Java中调用Com组件,由Com组件来帮助我们实现PDF的打印 工作,不够这条路也不是一帆风顺那!
  我们知道,Acrobat Reader在发布的时候会随同发布一个支持浏览器的com组件用来manipulate他的这个PDF文档格式,所以,我们想要本地调用这个随同发布的 Com组件来实现PDF打印。虽然Version5,6,7的这个组件格式不一样(5,6是以ocx的格式发布,7是以dll的格式发布),但是,不管那 么些,先从7开始吧!
  要调用com,那么我们需要一个从java到com的Bridge,所以,jacob第一个跃入我的脑海,因为之前就用过嘛!但是麻烦来了,我们并不知道 这个com组件提供了那些调用接口啊!哎,没办法,回学校求教熟悉.net的同学,给好不容易弄出几个需要的调用方法(哎,可怜我的周末啊),星期一就回 来用jacob调用啦,可是左试右试就是一直抛异常,我那个气啊!难道是jacob的为问题?!我就又找了jcom和jcom2等类似的产品,但jcom 全是日文文档,没有办法,而jcom2估计也是一个德行(我忘了为什么当初否决了这个),所以就决定试一试商业产品吧!
  这方面的商业产品主要有J-Integra,JPanel(好像叫这个名字)以及一个叫JNIWrapper的产品(这个是一个人用用来演示在java中 使用Acrobat5打印PDF的时候提到的)。这些商业产品好的地方就是他可以根据某个你要调用的com组件为你自动生成相应的Proxy对象java 代码,这样你就可以直接调用你熟悉的java代码了。像jacob等开源项目,如果给出一个类似的code generation工具的话,就完全不逊于这些商业产品啦。鉴于商业产品的价格,我最终还是否决了这些(日本人其实也听抠门的)。
  这样,Java-com也对这个问题没辙了。
  不过,最后在我的解决方案中,我还是使用了Jacob,这是后话,暂且不提...
  
  那我们考虑一下,如果PDF打印不行,打印其他格式行不行?!比如图片,这个JPS可以完全打印,所以,我们找一下有没有将PDF格式转换为其他格式的工 具吧!

  PDF格式转换的解决方案:
  在这个领域,主要的就是有GhostScript/GView和ImageMagick,前者可以将PDF格式转换为PostScript格式,但是好像 GhostScript也不能用JPS完全打印出来;而后者是一个将PDF转换为Image的API工具,他的Java实现叫JMagick,但他有一个 跟GhostScript同样的问题,就是要转换,就必须在本地安装,然后通过命令行的方式调用,这个显然也不是很好,而且集成性很差,还是作罢!
  
  剩下的一个是命令行调用啦,这是从itext网站找到的,你可以通过在命令行运行AcroRd32 /p /h "path to PDF file"这样的命令来打印你要打印的PDF文件,当然,你可以在PDF文件生成后就将他们依次放入一个批处理文件来执行这些打印命令,但是这个方案唯一 的问题就是,每打印一个文件都会启动一个Acrobat Reader窗口而且必须手动关闭,这现在不能满足目前的系统要求。
  好了,所有的方案基本上都罗列完了,也没有找到一个可行的方案:-(
  (没有银子嘛,不然Activetree的JPrint不错的说)
  
  这些东西差不多郁闷了我3,4天吧,那几天简直就是bored to death.
  
  不过,在郁闷的这几天的结尾,却有一道灵光闪过我的脑海...
  能不能说启动一个打印service,当文档要打印的时候,直接发送给它就行了那?!而恰好我发现一段在网页中加载PDF文档的javascript代 码,而且完全可以使用js来控制PDF的打印,所以,最终的这个方案就浮出水面了 ...
  1-使用jacob启动一个IE进程,并隐藏IE窗口;
  if(ieAutomation == null)
  ieAutomation = new ActiveXComponent("InternetExplorer.Application");
  ieAutomation.setProperty("Visible",new Variant(false));
  2-PDF前端在生成PDF文件之后发送生成后的文件到JacobPDFPrinter,JacobPDFPrinter根据出入的PDF文件的全路径使 用Velocity模板引擎动态生成一个包含使用Javascript代码实现的PDF打印逻辑的html文档(当然,使用Velocity生成文档这部 分逻辑我们单独抽出到VeloIEPrinterGenerator类中);
  3-在HTML生成之后,在JacobPDFPrinter中就可以使用jacob调用IE的Navigate2,将IE重定向到刚才生成的这个HTML 文件啦,这样,IE就会在后台调用JS代码将PDF打印到默认打印机;
  4-打印成功之后,清除临时动态生成的HTML文件;
  5-当主程序退出之前,Quit后台IE进程。
  以上就是我能给出的一个solution,并不完美,但it works.
  需要注意的几个问题是:
  (1)需要设置IE的一个高级选项,运行本地脚本运行;
  (2)因为Java和Com线程模型的不一致,导致在最终Quit后台IE进程的时候会抛出Com调用异常,因为对于Win平台API以及相关编程模型不 是很熟悉,所以,这个问题需要求助于别人帮忙解决;
  (3)IE在执行JS打印PDF的时候,同样会后台启动Acrobat的一个进程,而这个进程我们程序中无法控制其生命周期,所以,主程序退出后,我们没 有办法同时kill这个进程,好在不管我们运行多少次,这个进程在后台只有一个,所以,性能负担不是很大;
转载本回答被提问者和网友采纳

如何使用 JavaScript 将 pdf 文件直接发送到打印机?

【中文标题】如何使用 JavaScript 将 pdf 文件直接发送到打印机?【英文标题】:How to send a pdf file directly to the printer using JavaScript? 【发布时间】:2011-10-27 19:02:45 【问题描述】:

如何使用 JavaScript 将 PDF 文件直接发送到打印机?

我在一个论坛找到了两个答案:

<embed src="vehinvc.pdf" id = "Pdf1" name="Pdf1" hidden>
<a onClick="document.getElementById('Pdf1').printWithDialog()" style="cursor:hand;">Print file</a>

<OBJECT id = "Pdf2" name="Pdf2" CLASSID="clsid:CA8A9780-280D-11CF-A24D-444553540000" WIDTH="364" HEIGHT="290">
     <PARAM NAME='SRC' VALUE="file.pdf">
</OBJECT>
<a onClick="document.Pdf2.printWithDialog()">Print file</a> 

但我的问题是它只能在 IE 上运行,而不能在 Firefox 或 Chrome 上运行。

有什么解决办法吗?

【问题讨论】:

这个问题是关于 Adob​​e Reader 的插件 API 的吗? 我不认为这与 adobe reader 的插件有关。因为我在所有浏览器中都有相同版本的 adobe reader。但这段 JavaScript 代码仍然不能在 Internet Explorer 中工作。 @Jignesh Manek:我不相信你会为所有浏览器找到解决方案。您可以期待的最好的结果是打开打印对话框,老实说,这应该已经足够好了。作为用户,我最不想做的就是让我的打印机开始打印一些东西,而没有机会检查我的设置、纸张尺寸、托盘等。想想看……甚至是你的大多数各种应用程序、文字处理器、电子表格等也只需调用打印对话框。 @Sparky672:是的,你是真的。但使用此代码,Firefox 甚至不显示打印对话框.. @Jignesh Manek:那你到底想要什么?是否可以只在所有浏览器中打开打印对话框?此线程有更多信息:***.com/questions/687675/… 【参考方案1】:

我认为这个 JavaScript 库可能会对您有所帮助:

它叫Print.js

首先包含

<script src="print.js"></script>
<link rel="stylesheet" type="text/css" href="print.css">

基本用法是调用printJS(),传入一个PDF文档的url:printJS('docs/PrintJS.pdf')

我做的是这样的,如果PDF文档太大,这也会显示“正在加载...”。

<button type="button" onclick="printJS(printable:'docs/xx_large_printjs.pdf', type:'pdf', showModal:true)">
    Print PDF with Message
</button>

但请记住:

Firefox 目前不允许使用 iframe 打印 PDF 文档。在 Mozilla 的网站上有一个公开的bug 与此相关。使用 Firefox 时,Print.js 会将 PDF 文件打开到新选项卡中。

【讨论】:

这个库可以用来绕过打印对话框打印 PDF 吗? 你应该试一试,看看...!我不确定@W.M. ! @W.M.使用这个库可以绕过打印对话吗?【参考方案2】:

您需要采取两个步骤。

首先,您需要将 PDF 放入 iframe。

  <iframe id="pdf" name="pdf" src="document.pdf"></iframe>

要打印 iframe,您可以在此处查看答案:

Javascript Print iframe contents only

如果您想在 PDF 加载后自动打印 iframe,您可以将 onload 处理程序添加到 &lt;iframe&gt;

  <iframe onload="isLoaded()" id="pdf" name="pdf" src="document.pdf"></iframe>

加载器可能如下所示:

function isLoaded()

  var pdfFrame = window.frames["pdf"];
  pdfFrame.focus();
  pdfFrame.print();

这将显示浏览器的打印对话框,然后只打印 PDF 文档本身。 (我个人使用 onload 处理程序来启用“打印”按钮,以便用户可以决定是否打印文档)。

我在 Safari 和 Chrome 中几乎逐字使用此代码,但尚未在 IE 或 Firefox 上尝试。

【讨论】:

我在 Chrome、IE 和 Firefox 中尝试过这种方法,但它没有按预期工作。在 Chrome 中,我得到“pdfFrame.print 不是函数”。在 FF 中,我得到“错误:访问属性“打印”的权限被拒绝”。 IE 没有给出错误但不会触发打印对话框。 PDF 位于同一来源,并且 X-Frame-Options 设置为 SAMEORIGIN。这种方法是不是已经过时了?【参考方案3】:

这实际上使用 dataURI 更容易,因为您可以在返回的窗口对象上调用 print。

// file is a File object, this will also take a blob
const dataUrl = window.URL.createObjectURL(file);

// Open the window
const pdfWindow = window.open(dataUrl);

// Call print on it
pdfWindow.print();

这会在新选项卡中打开 pdf,然后弹出打印对话框。

【讨论】:

这是否适用于 xlsx 或 docx 等其他文件类型?【参考方案4】:

试试这个:有一个按钮/链接打开一个网页(在一个新窗口中),其中只嵌入了 pdf 文件,然后打印网页。

在主页的头部:

<script type="text/javascript">
function printpdf() 

myWindow=window.open("pdfwebpage.html");
myWindow.close;  //optional, to close the new window as soon as it opens
//this ensures user doesn't have to close the pop-up manually

</script>

在主页的正文中:

<a href="printpdf()">Click to Print the PDF</a>

pdfwebpage.html内部:

<html>
<head>    
</head>

<body onload="window.print()">
<embed src="pdfhere.pdf"/>

</body>
</html>

【讨论】:

这种方法对我来说似乎根本不起作用。 Chrome、IE 和 FireFox 的行为方式都相同 - 会出现一个打印对话框,但它只是打印带有小/不可见的嵌入式 PDF 的网页。我需要触发 PDF 打印,而不是网页打印。我错过了什么吗?【参考方案5】:

一个容纳打印触发器的函数...

function printTrigger(elementId) 
    var getMyFrame = document.getElementById(elementId);
    getMyFrame.focus();
    getMyFrame.contentWindow.print();

一个授予用户访问权限的按钮...

(an onClick on an a or button or input or whatever you wish)

<input type="button" value="Print" onclick="printTrigger('iFramePdf');" />
an iframe pointing to your PDF...

<iframe id="iFramePdf" src="myPdfUrl.pdf" style="dispaly:none;"></iframe>

更多:http://www.fpdf.org/en/script/script36.php

【讨论】:

再一次,它在 Firefox 和 Chrome 中什么也不做。在 IE 中进行测试时,主要的 html 文件内容被发送到打印机!【参考方案6】:
<?php

$browser_ver = get_browser(null,true);
//echo $browser_ver['browser'];

if($browser_ver['browser'] == 'IE') 
?>

<!DOCTYPE html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>pdf print test</title>
<style>
    html  height:100%; 
</style>
<script>
    function printIt(id) 
        var pdf = document.getElementById("samplePDF");
        pdf.click();
        pdf.setActive();
        pdf.focus();
        pdf.print();
    
</script>
</head>

<body style="margin:0; height:100%;">

<embed id="samplePDF" type="application/pdf" src="/pdfs/2010/dash_fdm350.pdf"   />
<button onClick="printIt('samplePDF')">Print</button>


</body>
</html>

<?php
 else 
?>
<HTML>
<script Language="javascript">

function printfile(id)  
    window.frames[id].focus();
    window.frames[id].print();
 

</script>
<BODY margin margin>

<iframe src="/pdfs/2010/dash_fdm350.pdf" id="objAdobePrint" name="objAdobePrint"   frameborder=0></iframe><br>

<input type="button" value="Print" onclick="javascript:printfile('objAdobePrint');">

</BODY>
</HTML>
<?php

?>

【讨论】:

OP 没有要求 PHP 解决方案。 我的问题中的代码已经在 IE 上工作了。我想要修复 firefox 和 chrome !

以上是关于如何在java中用javascript来打印pdf的主要内容,如果未能解决你的问题,请参考以下文章

在 php 或 javascript 上自动打印 PDF 脚本

如何在python中用markdown语言写一份报告并输出成PDF格式

如何使用 JavaScript 将 pdf 文件直接发送到打印机?

jsp 如何通过js来打印pdf文件!pdf存储在文件服务器上!

java如何实现在web工程中用OpenOffice生成带有图片水印的pdf

如何使用 jquery\javascript 从 firefox 浏览器打印 PDF 文档?