(HTML) Scarica un file PDF invece di aprirlo nel browser quando fai clic


115

Mi chiedevo come rendere scaricabile un collegamento a un file PDF invece di aprirli nel browser? Come si fa in html? (Presumo che sia fatto tramite javascript o qualcosa del genere).


3
Per quanto ne so, questo è un comportamento non programmabile. La maggior parte dei browser avrà le proprie impostazioni per il comportamento di cosa fare con tipi di file specifici durante il download.
Bart

1
A partire da HTML5, l'OP dovrebbe aggiornare la risposta corretta alla risposta di Sarim.
Omar Tariq


Questa domanda ha avuto risposta anche qui: stackoverflow.com/a/30714824/847235
intrepidis

Risposte:


38

Non puoi farlo con HTML. È una soluzione basata su server. È necessario eseguire lo streaming del file in modo che il browser attivi la finestra di dialogo di salvataggio.

Consiglierei di non farlo. Il modo in cui un utente interagisce con un PDF dovrebbe essere lasciato all'utente.

AGGIORNAMENTO (2014):

Quindi ... questa risposta riceve ancora molti voti negativi. Presumo che parte di ciò sia che questo è stato risposto 4 anni fa e come fa notare Sarim, ora c'è l' attributo HTML 5download che può gestirlo.

Sono d'accordo e penso che la risposta di Sarim sia buona (probabilmente dovrebbe essere la risposta scelta se l'OP ritorna). Tuttavia, questa risposta è ancora il modo affidabile per gestirla (come sottolinea la risposta di Yiğit Yener e - stranamente - le persone sono d'accordo). Sebbene l'attributo download abbia ottenuto il supporto, è ancora imprevedibile:

http://caniuse.com/#feat=download


18
So che ha un anno, ma non sono d'accordo. Ci sono circostanze in cui forzare questo comportamento è molto importante per il flusso dell'applicazione. La risposta effettiva è impostare la disposizione del contenuto nell'intestazione in modo che sia "allegato" anziché "in linea".
user158017

9
Concordo sul fatto che in altre circostanze è meglio lasciare il controllo dell'utente. Tuttavia, sono arrivato a questo thread cercando una risposta e la "risposta" selezionata non era una risposta, ma "non dovresti farlo". Per me, questa non è una risposta alla domanda. Invece, dai un specifica risposta e anche consigli.
user158017

1
A volte la domanda è sbagliata. ;) Comunque, per quanto riguarda il tuo problema, è tutto un problema di UX. Forzare il Web a comportarsi in modi specifici a volte è necessario, ma spesso ci sono soluzioni migliori dal punto di vista della UX. Inoltre, la mia risposta è corretta. Non puoi fare quello che vuoi fare con l'HTML (che è ciò che la domanda stava chiedendo). È una soluzione lato server.
DA.

1
Questa è una delle mie risposte più strane mai pubblicate. Le persone trovano ancora la loro strada qui per downvote. Che va bene! Ma sarebbe interessante sapere perché.
DA.

3
Riguardo a quel voto negativo, potrebbe essere la rovina della civiltà quanto sia facile imbattersi in un testo involontariamente arrogante . Questa risposta mi colpisce a patto che sia paternalistico e a corto di risposte. Invece del paragrafo 1, aggiungi semplicemente il httptag alla domanda. Invece del paragrafo 2: "Potresti voler riconsiderare se impedire la visualizzazione immediata del PDF è nel migliore interesse di tutti gli utenti. Detto questo ..." Quindi presumi che l'OP e i futuri lettori siano adulti e passa a una risposta utilizzabile come quella di Yener .
Bob Stein

133

Con html5, ora è possibile. Imposta un elemento "download" nell'elemento.

<a href="http://link/to/file" download="FileName">Download it!</a>

Fonte: http://updates.html5rocks.com/2011/08/Downloading-resources-in-HTML5-a-download


È meglio che tu scelga questa soluzione se è supportata. Ecco un modo per verificare se èif ("download" in document.createElement("a")){ ... }
pmrotule

Ho aggiunto un'altra risposta di seguito (brutto hack però), mentre questo è ancora il modo preferito, forse il modo di hacking potrebbe essere offerto per i browser non supportati.
Sarim

C'è un modo per specificare il testo per il pdf invece di menzionare il percorso del file? Ho bisogno di creare pdf da un div html ma non desidero aprire un'altra finestra, il download dovrebbe essere simile a questa risposta ..
T.Adak

1
Come in questo momento agosto 2019, il supporto del browser sembra essere migliorato per questa funzione, vedere: w3schools.com/tags/att_a_download.asp
Daniel Resch

2
Tieni presente che l'attributo di download è supportato solo per le richieste della stessa origine.
Quentin

82

Ciò è possibile solo impostando un'intestazione di risposta http dal codice lato server. Vale a dire;

Content-Disposition: attachment; filename=fname.ext

2
questa è la risposta perfetta: basta trovare il modo per farlo nella lingua lato server appropriata.
user158017

Esempio di Apache . Esempio di boccetta .
Bob Stein

Sfortunatamente iOS continuerà a visualizzare in anteprima e non scaricare i file PDF anche se la disposizione del contenuto è "allegato".
Jorn van de Beek

14

È necessario modificare le intestazioni http inviate. A seconda del tuo server, puoi modificare il tuo .htaccess come segue:

<FilesMatch "\.(?i:pdf)$">
  ForceType application/octet-stream
  Header set Content-Disposition attachment
</FilesMatch>

Non è necessario mentire sul tipo di contenuto. L'impostazione della disposizione del contenuto è sufficiente.
Quentin

9

dovrai usare uno script PHP (o un altro linguaggio lato server per questo)

<?php
// We'll be outputting a PDF
header('Content-type: application/pdf');

// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// The PDF source is in original.pdf
readfile('original.pdf');
?>

e usa explore per reindirizzare (riscrivere) al file PHP invece che al pdf


Hmm, funziona benissimo quando apro direttamente il file php. Ma quando provo a usare il reindirizzamento, come qui: Redirect 301 /_PDFs/Catalogue.pdf http://www.example.com/_PDFs/___download_the_catalogue_instead_opening.phpe provo ad aprire il file pdf, si apre ancora l'originale nel browser, scaricando invece la versione rinominata ...
ellockie

AGGIORNAMENTO: Funziona quando non ci sono file che vengono chiamati direttamente (come "Catalogue.pdf" nel mio esempio). Quindi il reindirizzamento funziona perfettamente. Grazie!
ellockie

8

Puoi usare

Response.AddHeader("Content-disposition", "attachment; filename=" + Name);

Guarda questo esempio:

http://www.codeproject.com/KB/aspnet/textfile.aspx

Questo vale per ASP.NET. Sono sicuro che puoi trovare soluzioni simili in tutte le altre lingue lato server. Tuttavia non esiste una soluzione javascript al meglio delle mie conoscenze.


questa è la risposta (così come quella correlata per PHP). il punto è che l'intestazione della risposta http deve essere modificata.
user158017

5

Senza l'attributo html5 si può ottenere ciò utilizzando php:

Crea un file php denominato download.php con questo codice:

<?php
ob_start();
$file = "yourPDF.pdf"

if (file_exists($file)) 
{
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit();
}

Ora se vuoi avviare automaticamente il download del pdf scrivi questo javascript:

<script>window.location = "download.php";</script>

Se vuoi che funzioni su un collegamento, usa questo ...

<a href='javascript:window.location = "download.php"'>
    Download it!
</a>

4
Solo un avvertimento che devi stare attento quando lo farai con i parametri URL. Ad esempio $file = $_GET['$file'];. Perché si potrebbe quindi anche chiamare download.php?file=../../../wp-config.phpo qualsiasi altra risorsa data. Il controllo aggiuntivo di estensioni, tipi MIME e percorsi consentiti da cui scaricare (e rimuovere elementi come "../") è molto importante!
Giel Berkers

sono io o fare <a href='javascript...'> è esattamente lo stesso che inserire direttamente il link<a href='download.php'> ?
allan.simon

5

Quando vuoi scaricare direttamente qualsiasi immagine o file pdf dal browser invece di aprirlo in una nuova scheda, allora in javascript dovresti impostare il valore per scaricare l'attributo di creare un collegamento dinamico

    var path= "your file path will be here"; 
    var save = document.createElement('a');  
    save.href = filePath; 
    save.download = "Your file name here"; 
    save.target = '_blank'; 
    var event = document.createEvent('Event');
    event.initEvent('click', true, true); 
    save.dispatchEvent(event);
   (window.URL || window.webkitURL).revokeObjectURL(save.href);

Per il nuovo aggiornamento di Chrome alcuni eventi temporali non funzionano. per quel codice verrà utilizzato il seguente

  var path= "your file path will be here"; 
    var save = document.createElement('a');  
    save.href = filePath; 
    save.download = "Your file name here"; 
    save.target = '_blank'; 
    document.body.appendChild(save);
    save.click();
    document.body.removeChild(save);

L'aggiunta e la rimozione di un bambino è utile per Firefox, solo per il browser Internet Explorer. Su Chrome funzionerà senza aggiungere e rimuovere il bambino


2

La soluzione che ha funzionato meglio per me è stata quella scritta da Nick sul suo blog

L'idea di base della sua soluzione è quella di utilizzare il mod di intestazione dei server Apache e modificare .htaccess per includere una direttiva FileMatch che costringe tutti i file * .pdf ad agire come un flusso invece di un allegato. Sebbene ciò non implichi effettivamente la modifica dell'HTML (come da domanda originale) non richiede alcuna programmazione di per sé.

Il primo motivo per cui ho preferito l'approccio di Nick è perché mi ha permesso di impostarlo in base alla cartella in modo che i PDF in una cartella potessero ancora essere aperti nel browser consentendo agli altri (quelli che vorremmo che gli utenti modificassero e quindi ricaricassero) da forzare come download.

Vorrei anche aggiungere che esiste un'opzione con i PDF per inviare / inviare moduli compilabili tramite un'API ai tuoi server, ma l'implementazione richiede del tempo.

La seconda ragione è che il tempo è una considerazione. Anche la scrittura di un gestore di file PHP per forzare la disposizione del contenuto nell'header () richiederà meno tempo di un'API, ma comunque più tempo dell'approccio di Nick.

Se sai come attivare una mod Apache e modificare il file .htaccss, puoi ottenerlo in circa 10 minuti. Richiede hosting Linux (non Windows). Questo potrebbe non essere un approccio appropriato per tutti gli usi in quanto richiede l'accesso al server di alto livello per la configurazione. Pertanto, se hai detto accesso è probabilmente perché sai già come fare queste due cose. In caso contrario, controlla il blog di Nick per ulteriori istruzioni.


2

Poiché il modo html5 (la mia risposta precedente) non è disponibile in tutti i browser, ecco un altro modo leggermente hackerato.

Questa soluzione richiede che tu stia servendo il file previsto dallo stesso dominio, OPPURE abbia l'autorizzazione CORS.

  1. Prima scarica il contenuto del file tramite XMLHttpRequest (Ajax).
  2. Quindi crea un URI dati codificando in base64 il contenuto del file e imposta il tipo di supporto su application/octet-stream. Il risultato dovrebbe assomigliare

data:application/octet-stream;base64,SGVsbG8sIFdvcmxkIQ%3D%3D

Adesso imposta location.href = data. Ciò farà sì che il browser scarichi il file. Sfortunatamente non puoi impostare il nome o l'estensione del file in questo modo. Giocherellare con il tipo di media potrebbe produrre qualcosa.

Vedi i dettagli: https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs



1

Se stai usando HTML5 (e immagino che ora tutti lo usino), c'è un attributo chiamato download .

ex. <a href="somepathto.pdf" download="filename">

qui filenameè facoltativo, ma se fornito, prenderà questo nome per il file scaricato.


Purtroppo, devo ammettere che sono troppo stupido per capire questo tag. Metto questo: <a href="download/Curriculum_it.pdf.zip">Download curriculum</a>o quello: <a href="download/Curriculum_it.pdf.zip" download="Curriculum_it">Download curriculum</a>e non vedo assolutamente alcuna differenza nel modo in cui funziona. Entrambi stanno scaricando il mio .zip. E nel secondo l'utilizzo dell'opzione nome file sembra non fare assolutamente nulla.
Garavani

0

Il comportamento dovrebbe dipendere da come è impostato il browser per gestire i vari tipi MIME. In questo caso il tipo MIME è application / pdf. Se vuoi forzare il browser a scaricare il file puoi provare a forzare un diverso tipo MIME sui file PDF. Raccomando di non farlo perché dovrebbe essere la scelta degli utenti cosa accadrà quando apriranno un file PDF.



-1

Finalmente ho trovato ...... crea tag di ancoraggio dinamico e fai clic su di esso

<script> 
   $('#myclick').click(function(){
       $('body').append('<a id="link" href="mypdf.pdf" 
        download="Payment.pdf">&nbsp;</a>');
       $('#link')[0].click();
   });
</script>

"Payment.pdf" è solo per il nome personalizzato.


Non è necessario generare il collegamento in modo dinamico.
Quentin

Tieni presente che l'attributo di download è supportato solo per le richieste della stessa origine.
Quentin

Questa sembra essere la stessa risposta di questa di tre anni prima.
Quentin
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.