2012-05-09 18 views
17

Ho un requisito insolito. Essenzialmente ho bisogno di un modo in cui, quando l'utente fa clic su un link o un pulsante, riceveranno un PDF. La parte difficile è che il server non elaborerà la richiesta su tutti a meno che non venga inviata un'intestazione personalizzata (in caso contrario riterrà la persona che ha effettuato il logout e li invierà alla schermata di accesso).Richiedere un file con un'intestazione personalizzata

Al momento il modo in cui funziona l'intestazione non può essere modificato quindi per favore non soffermarsi su di esso; verrà modificato in futuro ed è un'applicazione interna di cui non ho alcun controllo.

Le opzioni che ho esplorato:

  • L'utilizzo di un iframe o semplicemente aprendo una nuova finestra con una sorta di percorso che restituirà il PDF. Questo non può funzionare perché non posso specificare l'intestazione richiesta per il PDF e verrei reindirizzato prima di raggiungere il PDF stesso.
  • L'utilizzo di un modulo e l'invio della richiesta non possono funzionare perché non è possibile aggiungere intestazioni personalizzate ai moduli (solo XHR e plug-in, AFAIK).
  • L'utilizzo di XHR non può funzionare perché, mentre è possibile aggiungere l'intestazione e recuperare il file, non è possibile salvarlo sul lato client.

Sembrerebbe mie uniche opzioni a questo punto sono essenzialmente:

  • utilizzare una sorta di plug-in come Flash o Silverlight per richiedere il file.
  • Forza la modifica del requisito molto prima del previsto in modo che non sia più necessaria un'intestazione.

C'è qualcosa che mi manca qui? Spero che qualcuno possa verificare le mie scoperte o indicarmi qualcosa che ho perso perché, per quanto posso dire, non c'è davvero nulla che io possa fare qui.

EDIT: Questo sembra apt e conferma quello che stavo pensando: XMLHttpRequest to open PDF in browser

+2

Che ne dici di aggiungere una specie di tunnel tra l'app e il tuo script? Il tunnel potrebbe interrogare l'app e ricevere il file, quindi impostare un'intestazione corretta prima di scaricare il file all'utente, quindi attivare effettivamente un download. Non so se questo è possibile per il tuo sistema, a seconda della sicurezza. –

+0

Un tunnel non è una cattiva idea, anche se non sono sicuro che potremmo implementarlo qui. Hmm. Grazie, ci penserò. – Kris

+1

Se è possibile fare a meno del supporto per IE <10 (non molto probabile, giusto?), È possibile utilizzare XMLHttpRequest Level 2 (XHR2) e Blob URL. Ecco un esempio: http://stackoverflow.com/q/9620497 Vedi anche http://stackoverflow.com/q/6165266 e http://www.html5rocks.com/en/tutorials/file/xhr2/ –

risposta

13

testato per funzionare in cromo:

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

È possibile modificare application/pdf a application/octet-stream di avere pronta download. Ma è abbastanza facile da scaricare anche dal lettore di Chrome.

In Firefox non succede nulla, suppongo sia perché non ho un plug-in per gestire application/pdf installato.Il passaggio a application/octet-stream richiederà un dl.

con IE suppongo avete bisogno di un qualche tipo di VBScript/ActiveX hackery

Se il file è enorme, con uri dati potrebbe bloccarsi il browser, in questo caso è possibile utilizzare BlobBuilder e Object URL.

+1

È possibile inserire un nome file personalizzato per il download? –

2

Invece di collegamento al file .PDF, invece fare qualcosa di simile

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

che emette un header personalizzato, si apre il PDF (sicurezza binaria) e stampa i dati nel browser dell'utente, quindi possono scegliere di salvare il PDF nonostante le impostazioni del browser. Il pdf_server.php dovrebbe essere simile a questo:

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: L'unico modo per aggiungere intestazioni a una richiesta da all'interno di un browser (lato client) è utilizzare il metodo XmlHttpRequest setRequestHeader.

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

Questo è stato essenzialmente il mio primo pensiero, tuttavia, l'intestazione deve essere aggiunta sul lato client in quanto il server semplicemente non elaborerà nulla senza detta intestazione. Quindi, a meno che non utilizzi qualcosa tra il mio client e l'attuale architettura del server, non verrà eseguito niente sul lato server. – Kris

+0

Non è necessario aggiungere l'intestazione lato client. Questo dovrebbe funzionare fino a quando non c'è assolutamente alcun testo prima dell'intestazione nel file php. –

+0

Penso che tu abbia frainteso il mio requisito. Il server che genera il PDF richiede l'invio di un'intestazione personalizzata insieme a tutte le richieste. Se l'intestazione non viene inviata, si presume che l'utente sia disconnesso, che non venga eseguito alcun codice lato server e che la persona venga reindirizzata alla schermata di accesso. Sto cercando di confermare le mie scoperte poiché ritengo di essere incredibilmente limitato nel dimostrare una buona soluzione. – Kris

Problemi correlati