Ce que je veux construire, c’est qu’en cliquant sur un bouton, je veux déclencher l’impression d’un fichier PDF, mais sans l’ouvrir.
+-----------+
| Print PDF |
+-----------+
^ Click *---------> printPdf(pdfUrl)
La façon dont j'ai d'abord essayé est d'utiliser un iframe:
var $iframe = null;
// This is supposed to fix the onload bug on IE, but it's not fired
window.printIframeOnLoad = function() {
if (!$iframe.attr("src")) { return; }
var PDF = $iframe.get(0);
PDF.focus();
try {
// This doesn't work on IE anyways
PDF.contentWindow.print();
// I think on IE we can do something like this:
// PDF.document.execCommand("print", false, null);
} catch (e) {
// If we can't print it, we just open it in the current window
window.location = url;
}
};
function printPdf(url) {
if ($iframe) {
$iframe.remove();
}
$iframe = $('<iframe>', {
class: "hide",
id: "idPdf",
// Supposed to be a fix for IE
onload: "window.printIframeOnLoad()",
src: url
});
$("body").prepend($iframe);
}
Cela fonctionne sur Safari (desktop & iOS) et Chrome (peut-on généraliser peut-être à webkit?).
Sur Firefox, PDF.contentWindow.print()
se termine par une erreur permission denied
(Même le pdf est chargé à partir du même domaine).
Sur IE (11), le gestionnaire onload
ne fonctionne tout simplement pas.
Ma question est la suivante: existe-t-il un autre meilleur moyen d’imprimer le fichier PDF sans l’ouvrir visuellement à l’utilisateur?
La chose cross-browser est critique ici. Nous devrions supporter autant de navigateurs que possible.
Quel est le meilleur moyen d'y parvenir? Est-ce que mon début est un bon? Comment le compléter?
Nous sommes maintenant en 2016 et je pense que cela reste difficile à mettre en œuvre sur tous les navigateurs.
[~ # ~] update [~ # ~] : This link détaille une solution élégante qui implique la modification des propriétés de la page pour la première page et en ajoutant une action sur la page ouverte. Fonctionne sur tous les navigateurs (car les navigateurs exécuteront le code JavaScript placé dans la section actions). Nécessite Adobe Acrobat Pro.
Il semble que 2016 n'apporte aucune nouvelle avancée au problème de l'impression. Avait un problème similaire et pour faire l'impression cross-browser je l'ai résolu en utilisant PDF.JS mais ai dû faire un ajout d'un liner à la source (ils vous demandent de la construire de toute façon).
L'idée:
viewer.html
fichier est ce qui rend les PDF avec une interface riche et contient des fonctionnalités d'impression. J'ai ajouté un lien dans ce fichier à mon propre JavaScript qui ne fait que déclencher window.print () après un délai.Le lien ajouté à la visionneuse:
<script src="viewer.js"></script>
<!-- this autoPrint.js was added below viewer.js -->
<script src="autoPrint.js"></script>
</head>
Le autoPrint.js
javascript:
(function () {
function printWhenReady() {
if (PDFViewerApplication.initialized) {
window.print();
}
else {
window.setTimeout(printWhenReady, 3000);
}
};
printWhenReady();
})();
Je pourrais alors faire des appels à viewer.html?file=
dans le src d'un iframe et le cacher. Doit utiliser la visibilité, pas les styles d'affichage à cause de Firefox:
<iframe src="web/viewer.html?file=abcde.pdf" style="visibility: hidden">
Le résultat: la boîte de dialogue d’impression s’affiche après un bref délai, le PDF étant masqué par l’utilisateur).
Testé sous Chrome, IE, Firefox.
Après avoir passé les dernières heures à essayer de comprendre celui-ci et à effectuer de nombreuses recherches, voici ce que j'ai déterminé ...
Le spécification de l'API Web HTML5 pour l'impression indique que l'un des printing steps
doit déclencher beforeprint , un événement simple (événement non annulable) sur l’objet window du document en cours d’impression (ainsi que sur tout contexte de navigation imbriqué, il s’agit des iframes). permettre des modifications au document avant l'impression. Cette étape est interne au navigateur et n’est pas quelque chose que vous pourrez ajuster. Au cours de ce processus, la boîte de dialogue Imprimer du navigateur affiche parfois un aperçu du fichier (c'est ce que Chrome fait) ... donc, si votre objectif est de ne jamais afficher le fichier à la visionneuse, vous pourriez être bloqué.
Je suis venu le plus près de cet objectif en créant un index.html
fichier contenant un bouton contenant des attributs data- * fournissant un contexte. Changer le chemin/nom de fichier.ext dans le data-print-resource-uri
attribut à un fichier local de votre choix.
<!DOCTYPE html>
<html>
<head>
<title>Express</title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
<h1>Express</h1>
<p>Welcome to Express</p>
<button name="printFile" id="printFile" data-print-resource-uri="/binary/paycheckStub.pdf" data-print-resource-type="application/pdf">Print File</button>
<iframe name="printf" id="printf" frameborder="0"></iframe>
<script src="/javascripts/print.js"></script>
</body>
</html>
Puis dans le print.js
fichier, j’ai essayé quelques trucs, mais je n’ai jamais vraiment réussi à le faire (en laissant dans les commentaires des choses avec lesquelles j’avais joué).
// Reference vars
var printButton = document.getElementById('printFile');
var printFrame = document.getElementById('printf');
// onClick handler
printButton.onclick = function(evt) {
console.log('evt: ', evt);
printBlob('printf', printButton.getAttribute('data-print-resource-uri'), printButton.getAttribute('data-print-resource-type'));
}
// Fetch the file from the server
function getFile( fileUri, fileType, callback ) {
var xhr = new XMLHttpRequest();
xhr.open('GET', fileUri);
xhr.responseType = 'blob';
xhr.onload = function(e) {
// Success
if( 200 === this.status ) {
// Store as a Blob
var blob = new Blob([this.response], {type: fileType});
// Hang a URL to it
blob = URL.createObjectURL(blob);
callback(blob);
} else {
console.log('Error Status: ', this.status);
}
};
xhr.send();
}
function printBlob(printFrame, fileUri, fileType) {
// Debugging
console.log('inside of printBlob');
console.log('file URI: ', fileUri);
console.log('file TYPE: ', fileType);
// Get the file
getFile( fileUri, fileType, function(data) {
loadAndPrint(printFrame, data, fileType);
});
}
function loadAndPrint(printFrame, file, type) {
// Debugging
console.log('printFrame: ', printFrame);
console.log('file: ', file);
window.frames[printFrame].src = file;
window.frames[printFrame].print();
/*
// Setup the print window content
var windowContent = '<!DOCTYPE html>';
windowContent += '<html>'
windowContent += '<head><title>Print canvas</title></head>';
windowContent += '<body>'
windowContent += '<embed src="' + file + '" type="' + type + '">';
windowContent += '</body>';
windowContent += '</html>';
// Setup the print window
var printWin = window.open('','','width=340,height=260');
printWin.document.open();
printWin.document.write(windowContent);
printWin.document.close();
printWin.focus();
printWin.print();
printWin.close();
*/
}
Je pense que si vous pouvez le faire fonctionner correctement à l’aide de Blob
, celui-ci fonctionnera au mieux avec la méthode multi-navigateurs que vous souhaitiez.
J'ai trouvé quelques références sur ce sujet qui pourraient être utiles: