Pdf.js: Tidak dapat Mencetak PDF saat dimuat di iFrame

Dibuat pada 11 Okt 2014  ·  21Komentar  ·  Sumber: mozilla/pdf.js

Saya mencoba menggunakan Javascript untuk memfokuskan dan mencetak file PDF yang dimuat dalam iframe yang saya tempatkan secara dinamis ke dalam DOM. Masalah ini secara khusus terjadi untuk saya di Firefox.

Kode saya menyerupai berikut ini:

<iframe name="printer_frame" id="printer_frame" src="http://domain.com/media/eparcel_label_1413020567.pdf"></iframe>
window.frames['printer_frame'].window.focus();
window.frames['printer_frame'].window.print();

Saya menerima kesalahan berikut:

Kesalahan: Izin ditolak untuk mengakses properti 'cetak'

Penelitian saya memberi tahu saya bahwa ini seharusnya berhasil, bacaan lebih lanjut membuat saya percaya bahwa ini mungkin bug. Bantuan apa pun akan dihargai.

Sunting

Saya menguji fungsionalitas dengan mengganti file PDF dengan tangkapan layar dalam format PNG dari halaman pertama di dalamnya dan fungsi cetak berfungsi.

Sunting

Pengujian lebih lanjut. Menambahkan pdfjs ke pemasangan chrome saya, dan mencoba mencetak dengan kode yang sama di atas. kesalahan yang sama:

SecurityError: Memblokir bingkai dengan asal " http://domain.com " agar tidak mengakses bingkai lintas-asal.

code: 18
message: "Blocked a frame with origin "http://domain.com" from accessing a cross-origin frame."
name: "SecurityError"
stack:
"Error: Blocked a frame with origin "http://domain.com" from accessing a cross-origin frame.
    at Error (native)
    at <anonymous>:2:34
    at Object.InjectedScript._evaluateOn (<anonymous>:730:39)
    at Object.InjectedScript._evaluateAndWrap (<anonymous>:669:52)
    at Object.InjectedScript.evaluate (<anonymous>:581:21)"

Saya harus menjelaskan bahwa file PDF sedang dimuat di domain yang sama.

3-upstream 4-printing

Komentar yang paling membantu

Saya rasa saya tahu alasannya, setidaknya di Firefox. Dalam contoh sederhana seperti di atas, jika Anda menggunakan Firefox DevTools untuk memeriksa document.domain di halaman utama dan di iframe, saya menemukan bahwa document.domain adalah pdf.js untuk perender PDF.js—jadi pembatasan lintas-asal browser mulai berlaku.

Selain itu, jika saya membuat PDF.js dari sumber, dan menyetel iframe saya ke web/viewer.html?file= , lalu menelepon memberi tahu iframe untuk mencetak (seperti dalam OP), itu berfungsi dengan baik.

Apakah ada cara bagi PDF.js (setidaknya saat dijalankan di Firefox) untuk menerima pesan dari jendela lain, mungkin melalui sesuatu seperti window.postMessage ? (Saya belum pernah menggunakannya, jadi saya tidak tahu apakah itu sesuai untuk kasus penggunaan ini atau tidak.)

Semua 21 komentar

Mungkin duplikat dari bug 874200 .

Bagi siapa saja yang menemukan masalah ini dan menginginkan kemungkinan penyelesaian (mengingat masalah ini telah ada selama lebih dari satu tahun sekarang tanpa perbaikan), saya akhirnya menggunakan ImageMagick di PHP bersama dengan GhostScript untuk menghasilkan gambar PDF di server , lalu menampilkan URL gambar ini kembali dalam respons json, mencetak hasil dari itu adalah hal yang sepele.

Namun, mengetahui saya, mungkin ada cara yang lebih baik dan lebih mudah untuk melakukannya ...

di about:config saya set pdfjs.disabled=true tetapi pdf mulai mengunduh saya kira jika menggunakan plugin.disable_full_page_plugin_for_types = application/pdf tidak dapat mengunduh pdf dan di lihat di penampil

Saya rasa saya tahu alasannya, setidaknya di Firefox. Dalam contoh sederhana seperti di atas, jika Anda menggunakan Firefox DevTools untuk memeriksa document.domain di halaman utama dan di iframe, saya menemukan bahwa document.domain adalah pdf.js untuk perender PDF.js—jadi pembatasan lintas-asal browser mulai berlaku.

Selain itu, jika saya membuat PDF.js dari sumber, dan menyetel iframe saya ke web/viewer.html?file= , lalu menelepon memberi tahu iframe untuk mencetak (seperti dalam OP), itu berfungsi dengan baik.

Apakah ada cara bagi PDF.js (setidaknya saat dijalankan di Firefox) untuk menerima pesan dari jendela lain, mungkin melalui sesuatu seperti window.postMessage ? (Saya belum pernah menggunakannya, jadi saya tidak tahu apakah itu sesuai untuk kasus penggunaan ini atau tidak.)

Pengamatan lain: Saya berharap untuk memicu pencetakan melalui acara onload pada iframe , tetapi PDF belum tentu dirender. Tidak yakin apakah ada cara yang dapat diandalkan untuk memeriksanya?

Saya melihat #5765, tetapi tampaknya hanya merujuk ke acara yang dapat Anda kaitkan jika Anda menjalankan PDF.js secara langsung dan bukan versi Firefox bawaan?

Saya bingung bahwa ini adalah masalah untuk melakukan sesuatu yang sederhana seperti memicu file PDF untuk dicetak menggunakan javascript. Masalah ini tampaknya sudah ada dua tahun atau lebih (mungkin lebih lama) sekarang.

Adakah yang menemukan solusi _client side_? Saya melihat solusi @Petce tetapi solusi itu tidak berhasil untuk saya.

Jangan menahan nafas @Lynda333 , dukungan untuk masalah ini terkenal tidak responsif. Satu-satunya pilihan Anda yang sebenarnya menurut saya adalah menemukan kompromi yang sesuai dalam fungsionalitas. Jika Anda memberi tahu kami lebih banyak tentang situasi Anda sendiri dan orang lain mungkin dapat memberikan solusi yang mungkin.

@Petce - Saya tidak akan melakukannya ketika saya melihat sudah berapa lama masalah ini dimulai. Tampaknya konyol untuk tidak menyertakan kemampuan ini. Saya berbicara dengan klien dan akan mengubah pendekatan kami untuk situs ini. 1) Mereka dapat mengunduh PDF dan 2) Saya membuat ulang beberapa konten PDF dalam HTML dan membiarkan pengguna memilih apa yang akan dicetak. Membutuhkan lebih banyak waktu untuk membuat tetapi itu akan berhasil.

Adakah yang bisa mencetak iframe tertanam? saya baru saja menginstal versi ekstensi terakhir dan saya mendapatkan izin kesalahan ditolak, saya juga tidak dapat melihat file pdf pada akses pdf normal.

Menggunakan kode dari komit ini (dan pengurai data pdfjs itu sendiri), Anda dapat menulis ulang pdf Anda sebagai gumpalan sementara dan menambahkan instruksi cetak: https://github.com/mozilla/pdf.js/pull/6190/commits
Buat iframe dengan blob sebagai sumber dan itu akan mulai mencetak (Perhatikan bahwa ie tidak akan memuat blob ke dalam iframe sama sekali, selain tidak mengikuti instruksi cetak).
Bagaimanapun ini cukup rumit jika Anda belum menjalankan versi khusus penampil.
Atau Anda dapat menambahkan instruksi cetak di server atau di mana pun Anda dapat mengedit data pdf.

Bagian yang lucu adalah hanya firefox yang membutuhkannya... Sudah tiga tahun masalah ini dilaporkan dan firefox adalah satu-satunya browser yang mengeluh tentang mengakses iframe contentWindow: sepertinya tidak ada yang benar-benar peduli tentang pencetakan saat ini, yang mungkin merupakan hal yang baik.

Ini sepertinya berhasil untuk saya

        setTimeout(function(){
            this.printIframeRef.contentWindow.document.getElementById('secondaryPrint').click()
        }.bind(this), 3000)

Saya tidak dapat menemukan acara atau cara untuk menghubungkan ke penampil, tetapi jika Anda memicu klik bahkan pada tombol cetaknya (saya menggunakan versi 1.4.20) maka tampaknya akan dicetak. Settimeout memungkinkan waktu pemirsa untuk memuat dan semacamnya

Apakah Anda dapat mengakses contentWindow di firefox? Apakah Anda tidak mendapatkan masalah keamanan?

@paolocaminiti Saya memuat semua file dari domain yang sama. Tampaknya bekerja untuk saya. Saya telah menggunakan IE 10 dan 11, IE Edge, Chrome di Windows. Dan FireFox 38 di Ubuntu 14.04.

    handlePrintClick() {
        blurComponentRef(this.printButtonRef)
        this.printIframeRef.contentWindow.document.getElementById('secondaryPrint').click()
    }

    handlePrintLoad() {
        this.printIframeRef.contentWindow.addEventListener("documentload", function(){
            this.setState({canPrint: true})
        }.bind(this));
    }

Saya mengerti, Anda memuat pdf lagi dari jarak jauh dan itu menghasilkan domain yang sama.
Di chrome/opera/safari saya menggunakan ini:

function directPrint () {
  PDFViewerApplication.pdfDocument.getData().then(function(res) {
    var b = URL.createObjectURL(new Blob([res], { type: 'application/pdf' }))
    var printFrame = document.getElementById('print-frame')
    if (!printFrame) {
      printFrame = document.createElement('iframe')
      printFrame.id = 'print-frame'
      printFrame.src = b
      document.body.appendChild(printFrame)
    }
    setTimeout(function () {
      printFrame.contentWindow.print()
      // ...dispose iframe and blob.
    }, 0)
  })
}

Cukup menggunakan data lokal untuk membuat gumpalan dan kemudian memanggil print, setTimeout 0 memungkinkan iframe untuk dilampirkan.

Sayangnya firefox melarang contentWindow dengan blob, tetapi blob dengan instruksi cetak akan mencetak sendiri.

Untuk yaitu tidak ada solusi menggunakan data lokal, Tapi mungkin memiliki proxy di server yang memiliki satu untuk merutekan data pdf akan memungkinkan semua menjadi domain yang sama dan menerapkan kode Anda.

Halo,

Apa artinya "res"? Dan PDFViewerApplication berasal dari PDF.js?

Terima kasih,

Ya PDFViewerApplication disediakan oleh PDFViewer build dari pdfjs, sumbernya ada di bawah direktori /web, Anda harus memodifikasi di sana dan membuat build baru sehingga akan lebih mudah untuk menggabungkan master repo saat diperbarui...

res hanyalah argumen yang diteruskan kembali oleh getData, harus berupa rappresentasi byte dari file pdf, di sini digunakan untuk membangun url gumpalan lokal untuk dimuat tanpa permintaan jaringan lebih lanjut.

Jika Anda menginginkan sesuatu seperti kode di atas, Anda mungkin ingin sedikit membersihkannya:

function directPrint () {
  var printFrame = document.getElementById('print-frame')
  if (printFrame) {
    printFrame.contentWindow.print()
  } else {
    PDFViewerApplication.pdfDocument.getData().then(function(res) {
      var src = URL.createObjectURL(new Blob([res], { type: 'application/pdf' }))
      printFrame = document.createElement('iframe')
      printFrame.id = 'print-frame'
      printFrame.style.display = 'none'
      printFrame.src = src
      document.body.appendChild(printFrame)
      setTimeout(function () {
        printFrame.contentWindow.print()
      }, 0)
    })
  }
}

Pada akhirnya saya memilih untuk tidak membuang iframe karena terbukti menyulitkan untuk memahami kapan harus melakukannya, saya hanya membiarkannya di sana dan menggunakannya kembali setiap kali pengguna ingin mencetak, dengan asumsi pdf tidak dapat berubah di antaranya.

Semoga membantu.

@thenewguy Hanya untuk memperjelas utas ini untuk pembaca lain, sepertinya kami melakukan hal yang sangat berbeda:
Saya mencoba menggunakan penampil pdf browser asli untuk mencetak dalam kualitas penuh (saya tidak menemukan cara untuk mengakses contentWindow pada keduanya yaitu dan Edge tidak masalah menggunakan domain yang sama).
Anda memuat penampil PDFjs dalam iframe, mungkin terlihat, dan mengontrol pencetakannya dari aplikasi host.

Ini lucu karena saya mencoba mencapai @paolocaminiti memasukkan skrip ke iframe saya dan menyebutnya sebagai fungsi tetapi sekarang saya mendapatkan "offsetParent tidak disetel -- tidak dapat menggulir" . Saya akan menggunakan pencetakan kios chrome dan lupa ini.

Sejauh ini, tidak ada solusi yang diusulkan

Apakah saya masih perlu memiliki solusi sisi server atau apakah ada kemajuan dalam hal ini? Apakah mungkin menggunakan PDFPrintService dari pdf-js? Apakah ini akan menjadi solusi fungsional? Jika ya, bagaimana mungkin menggunakan layanan ini tanpa harus menggunakan seluruh pdf-viewer?

Apakah halaman ini membantu?
0 / 5 - 0 peringkat