javascript - 通过 iframe 将浏览器中的 PDF URL 发送到打印机

标签 javascript printing

对于当前的非 IE 浏览器(Chrome、Firefox、Opera、Safari),我想将 PDF 文档发送到给定该 PDF 的 URL 的打印机。

为了避免弹出多余的窗口,我目前正在使用 <iframe>但是我想在打印完成后关闭iframe,否则有些浏览器会在试图离开页面时弹出对话框。

这是我到目前为止的想法(为简单起见,使用 lodash 和 jQuery):

var _print_url, _remove_iframe, _set_print;

_print_url = function(src_url) {
  $("<iframe src='" + src_url + "' type='application/pdf'>").css({
    visibility: 'hidden',
    position: 'fixed',
    right: '0',
    bottom: '0'
  }).on('load', _set_print).appendTo(document.body);
};

_remove_iframe = function(iframe) {
  return $(iframe).parent().find(iframe).detach();
};

_set_print = function() {
  this.contentWindow.print();
/* 
 * Where we could do @contentWindow.close() with a window, we must remove the
 * print iframe from the DOM. We have to engage in some async madness
 * it seems, for no apparent reason other than this won't work
 * synchronously (@cw.print above must be async, it seems) - even though 
 * window.close() appears to work synchronously.
 */
  _.delay(_.partial(_remove_iframe, this), 100);
};

Sometimes it seems with Google Chrome the print-dialog ends up showing the PDF correctly, but when one selects the printer and confirms the intention to print it will actually send the contents of the frame's parent page to the printer instead of the PDF本身。

有一个链接 suggestions on the Mozilla page但这份文件目前似乎已经过时了。我能找到的最佳示例是对 Amazon Web Services 发票打印对话框进行逆向工程,但这会打开一个窗口。

我考虑过的一个替代方案是 Google Cloud Print ,但显然这需要安装额外的软件或配置 Google 帐户,除非必要,否则我不希望将这两者强加给用户。

是否有其他示例可以说明如何在给定 URL 的情况下打印 PDF,特别是使用 Javascript 并且没有其他多余的附加浏览器加载项或人工制品(例如弹出窗口)?

最佳答案

-- 注意使用这种方法你永远不会看到弹出窗口拦截器 --

几个月前,我在一个 ajax 应用程序中遇到了类似的问题,我遇到的问题是我需要创建 pdf 文件并在发送它进行打印之前存储,我所做的如下:

我没有使用 iframe。此应用程序使用 php TCPDF 创建 pdf,并使用 jqueryunderscore 作为模板系统。

您可以在http://www.screenr.com/Ur07 观看演示视频(2 分 18 秒)

  1. 通过 JSON (ajax) 发送信息 为了实现这一点,因为我遇到了一切都在 ajax 中的问题,所以我无法发布信息,所以我所做的是附加一个隐藏的 form 到 DOM,然后使用 target="_blank"将帖子发布到新窗口(您将在流程结束时关闭该窗口)。

HTML 隐藏虚拟表单

<form method='<%= method %>' 
      action="<%= action %>" 
      name="<%= name %>" 
      id="<%= id %>" 
      target="_blank">
    <input type='hidden' name='json' id='<%= valueId %>' />
</form>

Javascript

 function makePost(){
  var _t = _.template(_JS_Templates["print.form.hidden"]); //this the html of the form

  var o = {
    method : "POST",
    action : js_WEB_ + "/print.php",
    name : "print_virtual_form",
    id : "print_virtual_form_id",
    valueId : "print_virtual_value"
  }

 var form = _t(o);
 $(".warp").append(form); //appending the form to the dom

  var json = {
    data : data // some data
  }     

 $("#print_virtual_value").val(JSON.stringify(json)); //assing to the hidden input the value and stringify the json
 $("#print_virtual_form_id").submit(); //make the post submmitting the form
 $("#print_virtual_form_id").remove(); //removing the "virtual hidden form"

}

2.- 当你收到 json 时,我的情况是使用 php 你创建你必须创建的任何东西,我是这样做的,你可以在这个例子中看到 php 代码(是我的答案)

Generate PDF using TCPDF on ajax call

3.- 最后这是最酷的部分是响应,在这部分中,我使用 php 文件编写一个 javascript 代码,说明必须关闭父窗口并将 json 答案报告给特定的函数,是一种回调。

switch($_SERVER['REQUEST_METHOD']){
    case "GET":
        echo "Denied";
    break;

    case "POST":
        if(isset($_POST["json"])){
            if(!empty($_POST["json"])){
                $json = $_POST["json"];             
                $hash = PDF::makePDF($json);
                echo "<script>
                  function init() {
                        //calling callback
                                        //returning control to the previous browser
                                 window.opener.someclass.finish('".$hash."');
                                 window.close();
                    }
                window.onload = init;                       
             </script>";
            }else{
                echo "not json detected";
            }
        }else{
            echo "not json detected";
        }
    break;

4.- 最后,您可以在窗口浏览器中使用控件。

var someobject = (function(name){
  //private
  var finish(data){
    //do whatever you want with the json data
  }

   //public
   var $r = {};
   $r.finish = function(data){ 
     finish(data); //you will pass the data to the finish function and that is..!! voila!!
   }

   return $r;
})("someobject");

我知道这并不完全是您所要求的,而是解决同一问题的另一种方法,虽然我认为这稍微复杂一些,但我可以保证在很多浏览器中都能正常工作,并且用户会喜欢您的做法。他们永远不会看到发生了什么,他们会按照预期的方式下载文件,点击链接并保存文件。

只是我的两分钱和快乐的编码。

关于javascript - 通过 iframe 将浏览器中的 PDF URL 发送到打印机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17596043/

相关文章:

javascript - 如何在不修改模板的情况下在Google Blogger中添加jQuery?

javascript - Firefox 扩展中的 GMail 访问

javascript - 将拉伸(stretch)上的元素对齐到父 div 的中心

css - 打印预览压缩内容

ios - 如何在 iOS 4.2 中打印图像?

javascript - JavaScript 变量赋值中潜在的 XSS

javascript - 将脚本元素动态添加到 div 不会执行脚本

javascript - 在浏览器中打印图像

java - 如何打印 json 字符串?

python - 尝试在打印语句中用 % 替换普通 var