Demander un fichier avec un en-tête personnalisé

J'ai une exigence inhabituelle. Essentiellement, j'ai besoin d'un moyen pour que, lorsque l'utilisateur clique sur un lien ou un bouton, ils recevront un PDF. La partie délicate ici est que le serveur ne traitera pas la requête à moins qu'un en-tête personnalisé ne soit envoyé avec elle (sinon, la personne a déconnecté et les envoie à l'écran de connexion).

À l'heure actuelle, la façon dont l'en-tête fonctionne ne peut pas être modifiée, alors n'hésitez pas à y penser; Il sera changé à l'avenir et est une application interne sur laquelle je n'ai aucun contrôle.

Les options que j'ai explorées:

  • En utilisant un iframe ou simplement en ouvrant une nouvelle fenêtre avec une sorte de chemin qui renverra le PDF. Cela ne peut pas fonctionner car je ne peux pas spécifier l'en-tête requis pour le fichier PDF et je serais redirigé avant d'accéder au PDF lui-même.
  • L'utilisation d'un formulaire et la soumission de la demande ne peuvent pas fonctionner car je ne peux pas ajouter d'en-têtes personnalisés aux formulaires (seuls XHR et les plugins peuvent, AFAIK).
  • L'utilisation de XHR ne peut pas fonctionner car, bien qu'il puisse ajouter l'en-tête et récupérer le fichier, il n'y a aucun moyen de l'enregistrer sur le côté client.

Il semblerait que mes seules options à ce stade sont essentiellement:

  • Utilisez une sorte de plugin tel que Flash ou Silverlight pour demander le fichier.
  • Forcer le changement de l'exigence beaucoup plus tôt que prévu, de sorte qu'un en-tête n'est plus nécessaire.

Y at-il quelque chose que je manque ici? J'espère que quelqu'un peut vérifier mes découvertes ou me faire part de quelque chose que j'ai raté, car, pour autant que je le sache, il n'y a vraiment rien que je puisse faire ici.

EDIT: Cela semble apt et confirme ce que je pensais: XMLHttpRequest pour ouvrir le fichier PDF dans le navigateur

Testé pour travailler en chrome:

function toBinaryString(data) { var ret = []; var len = data.length; var byte; for (var i = 0; i < len; i++) { byte=( data.charCodeAt(i) & 0xFF )>>> 0; ret.push( String.fromCharCode(byte) ); } return ret.join(''); } var xhr = new XMLHttpRequest; xhr.open( "GET", "/test.pdf" ); //I had test.pdf this on my local server xhr.addEventListener( "load", function(){ var data = toBinaryString(this.responseText); data = "data:application/pdf;base64,"+btoa(data); document.location = data; }, false); xhr.setRequestHeader("magic", "header" ); xhr.overrideMimeType( "application/octet-stream; charset=x-user-defined;" ); xhr.send(null); 

Vous pouvez modifier l'application / pdf sur application / octet-stream pour obtenir l'invite de téléchargement. Mais il est assez facile de télécharger à partir du lecteur Chrome aussi.

Dans Firefox, rien ne se passe, je suppose que c'est parce que je n'ai pas de plugin pour traiter l' application/pdf installé. La modification à l'application / octet-stream provoquera un dl.

Avec IE, je suppose que vous avez besoin d'une sorte de fourmi VBScript / ActiveX

Si le fichier est énorme, l'utilisation des données uri risque de bloquer le navigateur. Dans ce cas, vous pouvez utiliser les URL de BlobBuilder et Object.

Au lieu de lier au fichier .PDF, préférez-vous quelque chose comme

 <a href="pdf_server.php?file=pdffilename">Download my eBook</a> 

Qui produit un en-tête personnalisé, ouvre le PDF (binaire sécurisé) et imprime les données au navigateur de l'utilisateur, alors ils peuvent choisir d'enregistrer le PDF malgré leurs paramètres de navigateur. Le pdf_server.php devrait ressembler à ceci:

 header("Content-Type: application/octet-stream"); $file = $_GET["file"] .".pdf"; header("Content-Disposition: attachment; filename=" . urlencode($file)); header("Content-Type: application/force-download"); header("Content-Type: application/octet-stream"); header("Content-Type: application/download"); header("Content-Description: File Transfer"); header("Content-Length: " . filesize($file)); flush(); // this doesn't really matter. $fp = fopen($file, "r"); while (!feof($fp)) { echo fread($fp, 65536); flush(); // this is essential for large downloads } fclose($fp); 

EDIT: La seule façon d'ajouter des en-têtes à une requête à partir d'un navigateur (côté client) utilise la méthode de configurationRequestHeader XmlHttpRequest.

 xhr.setRequestHeader('custom-header', 'value');