【问题标题】:Send a PDF URL in a browser to the printer via iframe通过 iframe 在浏览器中将 PDF URL 发送到打印机
【发布时间】:2013-07-11 14:25:43
【问题描述】:

对于当前的非 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);
};

有时它似乎在Google Chrome中,打印对话框最终正确显示PDF,但是当一个选择打印机并确认打印的意图时,它将实际将框架的父页面的内容发送到打印机而不是PDF自己。

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

我考虑过的另一种选择是Google Cloud Print,但显然这需要安装额外的软件或配置 Google 帐户,除非必要,否则我不希望将这些强加给用户。

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

【问题讨论】:

  • 这只是一个怀疑,但是如果你在调用print() 之前调用this.contentWindow.focus() 会发生什么?
  • @YatinSaraiya 它指的是 iframe。 jQuery 将this 绑定到定义了事件处理程序的元素。 (See here, last paragraph in the section.)

标签: javascript printing


【解决方案1】:

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

几个月前,我在一个 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");

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

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

【讨论】:

  • 非常感谢您加入讨论。这似乎是一个真正的利基问题,所以我很感激任何想法和想法,这看起来很棒。干杯。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-18
  • 2013-07-01
  • 2014-10-13
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
  • 2012-12-17
相关资源
最近更新 更多