2012-05-09 12 views
17

Ich habe eine ungewöhnliche Anforderung. Im Wesentlichen brauche ich eine Möglichkeit, dass der Benutzer, wenn er auf einen Link oder eine Schaltfläche klickt, eine PDF erhält. Der heikle Teil hier ist, dass der Server die Anfrage an allen nicht verarbeiten wird, es sei denn, ein benutzerdefinierter Header wird mit ihm gesendet (andernfalls wird die Person als abgemeldet betrachtet und an den Anmeldebildschirm gesendet).Fordern Sie eine Datei mit einem benutzerdefinierten Header

Im Moment kann die Art, wie die Kopfzeile funktioniert, nicht geändert werden, also bitte nicht darauf verweilen; Es wird sich in Zukunft ändern und ist eine interne Anwendung, auf die ich keine Kontrolle habe.

  • einen Iframe verwenden oder einfach ein neues Fenster mit einer Art Pfad öffnen, die PDF zurückkehren:

    Die Optionen habe ich untersucht. Dies kann nicht funktionieren, da ich die erforderliche Kopfzeile für die PDF-Datei nicht angeben kann und vor dem Erreichen der PDF-Datei umgeleitet würde.

  • Verwenden eines Formulars und das Senden der Anfrage kann nicht funktionieren, weil ich keine benutzerdefinierten Header Formulare hinzufügen kann (nur XHR und Plugins können, AFAIK).
  • Die Verwendung von XHR kann nicht funktionieren, weil, während es die Kopfzeile hinzufügen und die Datei abrufen kann, gibt es keine Möglichkeit, es auf der Clientseite zu speichern.

Es wäre meine einzigen Optionen an dieser Stelle erscheint, sind im Wesentlichen:

  • eine Art Plugin wie Flash oder Silverlight, die Datei anzufordern.
  • Erzwingen Sie die Änderung der Anforderung viel früher als erwartet, so dass eine Kopfzeile nicht mehr benötigt wird.

Gibt es etwas, das ich hier vermisse? Ich hoffe, dass jemand meine Ergebnisse überprüfen oder auf etwas hinweisen kann, das ich vermisst habe, denn soweit ich das beurteilen kann, gibt es hier wirklich nichts, was ich tun könnte.

EDIT: Dies scheint geeignet und bestätigt, was ich dachte: XMLHttpRequest to open PDF in browser

+2

Wie wäre es mit einer Art Tunnel zwischen der App und Ihrem Skript? Der Tunnel könnte die App abfragen und die Datei empfangen, und dann einen korrekten Header festlegen, bevor die Datei dem Benutzer gespült wird, wodurch tatsächlich ein Download ausgelöst wird. Ich weiß nicht, ob dies für Ihr System möglich ist, abhängig von der Sicherheit. –

+0

Ein Tunnel ist keine schlechte Idee, obwohl ich mir nicht sicher bin, ob wir das hier umsetzen können. Hmm. Danke, ich werde mich darum kümmern. – Kris

+1

Wenn Sie ohne Unterstützung für IE <10 (nicht sehr wahrscheinlich, richtig?), Können Sie XMLHttpRequest Level 2 (XHR2) und Blob URLs verwenden. Hier ein Beispiel: http://Stackoverflow.com/q/9620497 Siehe auch http://StackOverflow.com/q/6165266 und http://www.html5rocks.com/en/tutorials/file/xhr2/ –

Antwort

13

Getestet in Chrom zu arbeiten:

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); 

Sie können application/pdf auf application/octet-stream ändern herunterladen prompt zu haben. Aber es ist auch ziemlich einfach, es vom Chromleser herunterzuladen.

In Firefox passiert nichts, ich denke, es ist, weil ich kein Plugin mit application/pdf installiert haben.Wenn Sie in application/octet-stream wechseln, wird ein dl angezeigt.

Mit IE nehme ich Sie

eine Art von VBScript/ActiveX hackery benötigen Wenn die Datei sehr groß ist, Daten uri mit möglicherweise den Browser zum Absturz bringen, in diesem Fall können Sie BlobBuilder und URLs Objekt verwenden.

+1

Ist es möglich, einen benutzerdefinierten Dateinamen für den Download zu setzen? –

2

Statt auf die PDF-Datei zu verknüpfen, sondern wie etwas tun

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

, die einen benutzerdefinierten Header ausgibt, öffnet die PDF (binär sicher) und druckt die Daten in den Browser des Benutzers, dann können sie wählen, die PDF trotz ihrer Browsereinstellungen zu speichern. Die pdf_server.php sollte wie folgt aussehen:

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: Die einzige Möglichkeit, Header in einem Browser (Client-Seite) auf eine Anfrage hinzuzufügen, ist die XmlHttpRequest setRequestHeader Methode verwenden.

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

Dies war im Wesentlichen mein erster Gedanke, jedoch muss der Header clientseitig hinzugefügt werden, da der Server nichts ohne diesen Header verarbeitet. Also, es sei denn, ich verwende etwas zwischen meinem Client und der aktuellen Server-Architektur, würde nichts Server-Seite ausgeführt werden. – Kris

+0

Sie sollten die Kopfzeile clientseitig nicht hinzufügen müssen. Dies sollte funktionieren, solange absolut kein Text vor dem Header in der PHP-Datei vorhanden ist. –

+0

Ich denke, Sie missverstehen meine Anforderung. Der Server, der das PDF generiert, benötigt einen benutzerdefinierten Header, der mit allen Anforderungen gesendet wird. Wenn der Header nicht gesendet wird, wird angenommen, dass der Benutzer ausgeloggt ist, kein serverseitiger Code ausgeführt wird und die Person zum Anmeldebildschirm umgeleitet wird. Ich versuche, meine Ergebnisse zu bestätigen, da ich glaube, dass ich unglaublich gut darin bin, eine gute Lösung zu finden. – Kris

Verwandte Themen