Forza ad aprire il popup "Salva con nome ..." nel link testuale fare clic per PDF in HTML


173

Ho alcuni cataloghi PDF di grandi dimensioni sul mio sito Web e devo collegarli come download. Quando ho cercato su Google, ho trovato una cosa del genere riportata di seguito. Dovrebbe aprire il popup " Salva con nome ... " al link fare clic su ...

 <head>
    <meta name="content-disposition" content="inline; filename=filename.pdf">
    ...

Ma non funziona: / Quando collego a un file come di seguito, si collega a un file e sta cercando di aprire il file.

    <a href="filename.pdf" title="Filie Name">File name</a>

AGGIORNAMENTO (secondo le risposte di seguito):

Come vedo, non esiste una soluzione cross-browser affidabile al 100% per questo. Probabilmente il modo migliore è utilizzare uno dei servizi Web elencati di seguito e fornire un link per il download ...


1
non serve il mimetype per i file pdf.
bhups,

Ho provato la tua soluzione aggiornata, artmania - ma si è verificato lo stesso problema che ho riscontrato in Safari. Ottengo quello che sembra il PDF nella finestra del browser e solo quando faccio clic sulle schede "Anteprima" o "Scarica" ​​in basso ottengo la funzione di ricerca di cui ho così disperatamente bisogno.
Heathrower,


Risposte:


268

Da una risposta a Forza un browser per salvare il file come dopo aver fatto clic sul collegamento :

<a href="path/to/file" download>Click here to download</a>

17
Al momento di questo commento, l' downloadattributo è limitato a Chrome, Firefox e Opera. Anche le versioni recenti di IE e Safari non lo supportano. Per supporto futuro: controlla caniuse.com/#feat=download !
Sygmoral,

Il controllo degli errori di Netbeans si lamenta, ma sembra funzionare bene. È possibile specificare un nome preliminare per il nuovo file in questo modo: download = "myFile.txt"
Yster

1
Funziona in Edge al momento della stesura di questo commento e sembra l'unico modo possibile per impedire l'apertura di PDF con collegamento ipertestuale nel tentativo molto scarso di Edge di visualizzare un PDF.

Al momento di questo commento, l'ho provato su Chrome, Opera, Edge, Mozilla. Tutti gli ultimi Funziona su tutti tranne che su Mozilla.
SI,

7
Funziona solo con link della stessa origine, come menzionato su caniuse.com/#feat=download . Se i tuoi collegamenti sono di origine incrociata, l'unica opzione (per ora) è forzare il tipo di risposta a "application / octet-stream", come suggeriscono molte risposte. Se non hai accesso al server, puoi provare a proxy e impostare manualmente l'intestazione della risposta.
Jean-Baptiste,

81
<a href="file link" download target="_blank">Click here to download</a>

Funziona per me in Firefox e Chrome.


2
Tuttavia, è esattamente la stessa dell'attuale risposta principale, di Ayush Gupta nel 2013. Ciò target="_blank"potrebbe renderlo leggermente più utilizzabile per browser non supportati, tuttavia (i PDF si aprono in una nuova finestra / scheda, anziché sovrascrivere la pagina corrente).
Sygmoral,

3
Per me, è target="_blank"stato necessario perché downloadnon è stato possibile avviare correttamente il download (Chrome)
casraf,

2
Se si assegna una stringa downloadall'attributo, verrà utilizzata come nome del file. Lo sto usando sempre negli script utente.
weaknespase

34

I meta tag non sono un modo affidabile per ottenere questo risultato. Generalmente non dovresti nemmeno farlo - dovrebbe essere lasciato all'utente / agente utente per decidere cosa fare con il contenuto fornito. L'utente può sempre forzare il proprio browser a scaricare il file se lo desidera.

Se vuoi comunque forzare il browser a scaricare il file, modifica direttamente le intestazioni HTTP. Ecco un esempio di codice PHP:

$path = "path/to/file.pdf";
$filename = "file.pdf";
header('Content-Transfer-Encoding: binary');  // For Gecko browsers mainly
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($path)) . ' GMT');
header('Accept-Ranges: bytes');  // Allow support for download resume
header('Content-Length: ' . filesize($path));  // File size
header('Content-Encoding: none');
header('Content-Type: application/pdf');  // Change the mime type if the file is not PDF
header('Content-Disposition: attachment; filename=' . $filename);  // Make the browser display the Save As dialog
readfile($path);  // This is necessary in order to get it to actually download the file, otherwise it will be 0Kb

Si noti che questa è solo un'estensione del protocollo HTTP; alcuni browser potrebbero ignorarlo comunque.


4
In pratica, credo che questo sia ampiamente implementato.
Matthew Wilson,

Questa è la soluzione migliore, senza problemi e funziona. Puoi scaricare direttamente qualsiasi tipo di file usando questo metodo. +1
casraf,

3
Content-Transfer-Encoding non esiste in HTTP. Codifica contenuto: nessuno è inutile.
Julian Reschke,

FAI UNA NOTA nella tua risposta, che il file IF proviene da un server / dominio esterno, quindi questa risposta potrebbe non essere una soluzione ...
T.Todua,

Vorrei aggiungere che ho avuto questo o simile codice fallire su alcuni server quando i file diventano grandi (> 80 MB nel mio caso). L'uso ob_end_flush()non ha aiutato neanche.
Hendrik,

22

Ho avuto lo stesso problema e ho trovato una soluzione che finora ha funzionato alla grande. Inserisci il seguente codice nel tuo .htaccessfile:

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

Veniva da Forza un file da scaricare invece di apparire nel browser .


4
Funzionava bene, dato che avevo una particolare directory di documenti per i download. Ho omesso ForceType, solo per lasciare che i tipi rimangano così come sono. Inoltre non avevo bisogno del case-sensitive; la mia sembra non distingue tra maiuscole e minuscole. Ho aggiunto un paio di tipi extra, incluso optional-x per le vecchie / nuove estensioni di Office:<FilesMatch "\.(pdf|xlsx?|docx?)$">
addio

Questo ha funzionato meravigliosamente, anche in OSX Safari, dove altre risposte (inclusa quella accettata, come ha sottolineato un commentatore) sono limitate a determinati browser che supportano la funzione HTML fornita. Questo mi sembra più ideale dal momento che ha funzionato su tutta la linea, anche se richiede un accesso di livello superiore ai file di configurazione del server.
bwright,

Potresti metterlo bene anche nel tuo file apache.conf, non uso .htaccess in quanto richiede più risorse.
Michael Fever,

In che modo un sito Web ospitato da Windows implementerebbe questo, dal momento che non sono in grado di leggere i file htaccess?
PoloHole Impostato il

10

Ho trovato una soluzione molto semplice per Firefox (funziona solo con un href relativo anziché diretto): aggiungi type="application/octet-stream":

<a href="./file.pdf" id='example' type="application/octet-stream">Example</a>

1
@Martin Chrome su Chrome OS e Firefox su Linux. Risulta che il file deve essere locale affinché funzioni. Il mio href era un url per il cloud storage.
ttfreeman,

7

Prova ad aggiungere questa riga al tuo file .htaccess.

AddType application/octet-stream .pdf

Spero che funzioni poiché è indipendente dal browser.


Sarei interessato a sapere perché questo è stato sottoposto a downgrade: è uno dei metodi e dei metodi più semplici: css-tricks.com/snippets/htaccess/…
Nathan Hornby,

Le persone cercano di modificare la funzionalità principale di un server su siti di hosting gratuiti e quindi di effettuare il downvote perché non riescono a farlo funzionare. Ogni altra soluzione avrà avvertenze perché è un "hack" per sostituire questo.
Carrello abbandonato

Lo sto ridimensionando perché è la soluzione sbagliata al problema. È una cattiva idea pasticciare con tipi di risorse.
Brad

@NathanHornby - Non l'ho votato in basso, ma questo non funzionerebbe per nessun sito ospitato su Windows, poiché non usano .htaccess.
PoloHole Impostato il

Non ho effettuato il downgrade, ma questa soluzione influisce ciecamente su TUTTI i file di quel suffisso. È indiscriminato e quindi non sarà appropriato in tutti i casi.
JBH,

6

In genere succede, perché alcune impostazioni o plug-in del browser aprono direttamente il PDF nella stessa finestra come una semplice pagina Web.

Quanto segue potrebbe aiutarti. L'ho fatto in PHP qualche anno fa. Ma attualmente non sto lavorando su quella piattaforma.

<?php
    if (isset($_GET['file'])) {
        $file = $_GET['file'];
        if (file_exists($file) && is_readable($file) && preg_match('/\.pdf$/',$file)) {
            header('Content-type: application/pdf');
            header("Content-Disposition: attachment; filename=\"$file\"");
            readfile($file);
        }
    }
    else {
        header("HTTP/1.0 404 Not Found");
        echo "<h1>Error 404: File Not Found: <br /><em>$file</em></h1>";
    }
?>

Salvare quanto sopra come download.php .

Salva questo piccolo frammento come file PHP da qualche parte sul tuo server e puoi usarlo per effettuare un download di file nel browser, anziché visualizzarlo direttamente. Se desideri pubblicare file diversi dal PDF, rimuovi o modifica la riga 5.

Puoi usarlo in questo modo:

Aggiungi il seguente link al tuo file HTML.

<a href="download.php?file=my_pdf_file.pdf">Download the cool PDF.</a>

Riferimento da: questo blog


7
Questo sembra essere un buon modo per servire ogni singolo file sul tuo server a chiunque stia prestando attenzione. download.php?file=database_password_file.phpper esempio.
pbarney,

5

Inserisci il codice qui sotto nel tuo .htaccessfile:

AddType application/octet-stream .csv
AddType application/octet-stream .xls
AddType application/octet-stream .doc
AddType application/octet-stream .avi
AddType application/octet-stream .mpg
AddType application/octet-stream .mov
AddType application/octet-stream .pdf

Oppure puoi anche fare un trucco con JavaScript

element.setAttribute( 'download', whatever_string_you_want);

1
Questo non presuppone che il web server sia Apache ?
Peter Mortensen,


4

Un modo davvero semplice per raggiungere questo obiettivo, senza utilizzare siti di download esterni o modificare le intestazioni ecc. È semplicemente creare un file ZIP con il PDF all'interno e collegarlo direttamente al file ZIP. Ciò attiverà SEMPRE la finestra di dialogo Salva / Apri ed è ancora facile per le persone fare doppio clic sulle finestre PDF in cui viene avviato il programma associato a .zip.

A proposito grande domanda, stavo anche cercando una risposta, dal momento che la maggior parte dei plug-in PDF incorporati nel browser impiega così tanto tempo per visualizzare qualsiasi cosa (e spesso bloccherà il browser durante il caricamento del PDF).


31
Terribile usabilità. Molti utenti finali non saprebbero cosa fare con un file zip.
CodeWarrior,

1
A volte semplici solutioan sono le migliori soluzioni!
elrado,

1
Non è una buona soluzione. Ho esattamente quel problema con Firefox e un file ZIP. Cosa dovrei fare? ZIP il file? In tal caso, la modifica delle intestazioni HTTP potrebbe essere una soluzione, ma non ho accesso a ciò.
Arnaud Weil,

2

Una soluzione lato server è più compatibile, fino a quando l'attributo "download" non viene implementato in tutti i browser.

Un esempio di Python potrebbe essere un gestore di richieste HTTP personalizzato per un archivio file. I collegamenti che puntano al negozio di file sono generati in questo modo:

http://www.myfilestore.com/filestore/13/130787e71/download_as/desiredName.pdf

Ecco il codice:

class HTTPFilestoreHandler(SimpleHTTPRequestHandler):

    def __init__(self, fs_path, *args):
        self.fs_path = fs_path                          # Filestore path
        SimpleHTTPRequestHandler.__init__(self, *args)

    def send_head(self):
        # Overwrite SimpleHTTPRequestHandler.send_head to force download name
        path = self.path
        get_index = (path == '/')
        self.log_message("path: %s" % path)
        if '/download_as/' in path:
            p_parts = path.split('/download_as/')
            assert len(p_parts) == 2, 'Bad download link:' + path
            path, download_as = p_parts
        path = self.translate_path(path )
        f = None
        if os.path.isdir(path):
            if not self.path.endswith('/'):
                # Redirect browser - doing basically what Apache does
                self.send_response(301)
                self.send_header("Location", self.path + "/")
                self.end_headers()
                return None
            else:
                return self.list_directory(path)
        ctype = self.guess_type(path)
        try:
            f = open(path, 'rb')
        except IOError:
            self.send_error(404, "File not found")
            return None
        self.send_response(200)
        self.send_header("Content-type", ctype)
        fs = os.fstat(f.fileno())
        self.send_header("Expires", '0')
        self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
        self.send_header("Cache-Control", 'must-revalidate, post-check=0, pre-check=0')
        self.send_header("Content-Transfer-Encoding", 'binary')
        if download_as:
            self.send_header("Content-Disposition", 'attachment; filename="%s"' % download_as)
        self.send_header("Content-Length", str(fs[6]))
        self.send_header("Connection", 'close')
        self.end_headers()
        return f


class HTTPFilestoreServer:

    def __init__(self, fs_path, server_address):
        def handler(*args):
            newHandler = HTTPFilestoreHandler(fs_path, *args)
            newHandler.protocol_version = "HTTP/1.0"
        self.server = BaseHTTPServer.HTTPServer(server_address, handler)

    def serve_forever(self, *args):
        self.server.serve_forever(*args)


def start_server(fs_path, ip_address, port):
    server_address = (ip_address, port)
    httpd = HTTPFilestoreServer(fs_path, server_address)

    sa = httpd.server.socket.getsockname()
    print "Serving HTTP on", sa[0], "port", sa[1], "..."
    httpd.serve_forever()

2

Un modo molto semplice per eseguire questa operazione, se è necessario forzare il download per un singolo collegamento nella pagina, è utilizzare l'attributo di download HTML5 nel collegamento href.

Vedi: http://davidwalsh.name/download-attribute

con questo puoi rinominare il file che l'utente scaricherà e allo stesso tempo impone il download.

Si è discusso se questa è una buona pratica o meno, ma nel mio caso ho un visualizzatore incorporato per un file PDF e il visualizzatore non offre un link per il download, quindi devo fornirne uno separatamente. Qui voglio assicurarmi che l'utente non ottenga il PDF aperto nel browser Web, il che sarebbe confuso.

Ciò non sarà necessario per aprire la finestra di dialogo Salva con nome, ma scaricherà il collegamento direttamente nella destinazione di download preimpostata. E ovviamente se stai creando un sito per qualcun altro e hai bisogno che scrivano manualmente gli attributi ai loro collegamenti è probabilmente una cattiva idea, ma se c'è modo di ottenere l'attributo nei collegamenti, questa può essere una soluzione leggera.


1

Questo è un vecchio post, ma qui è la mia soluzione in JavaScript che cosa usando la libreria jQuery.

<script>
(function($){
    var download = [];
    $('a.force-download, .force-download a').each(function(){
        // Collect info
        var $this = $(this),
            $href = $this.attr('href'),
            $split = $href.split('/'),
            $name = document.title.replace(/[\W_]/gi, '-').replace(/-{2,}/g, '-'); // get title and clean it for the URL

        // Get filename from URL
        if($split[($split.length-1)])
        {
            $tmp = $split[($split.length-1)];
            $tmp = $tmp.split('.');
            $name = $tmp[0].replace(/[\W_]/gi, '-').replace(/-{2,}/g, '-');
        }

        // If name already exists, put timestamp there
        if($.inArray($name, download) > -1)
        {
            $name = $name + '-' + Date.now().replace(/[\W]/gi, '-');
        }

        $(this).attr("download", $name);
        download.push($name);
    });
}(jQuery || window.jQuery))
</script>

Devi solo usare la classe force-downloadall'interno del tuo <a>tag e forzare il download automaticamente. Puoi anche aggiungerlo al genitore dive raccoglierà tutti i collegamenti al suo interno.

Esempio:

<a href="/some/good/url/Post-Injection_Post-Surgery_Instructions.pdf" class="force-download" target="_blank">Download PDF</a>

Questo è ottimo per WordPress e qualsiasi altro sistema o sito Web personalizzato.


0

Dopo aver aggiunto il nome del file nel codice HTML ?forcedownload=1

Questo è stato il modo più semplice per me per attivare una finestra di dialogo per salvare o scaricare.


0

Se hai un plugin nel browser che sa come aprire un file PDF, questo si aprirà direttamente. Come nel caso di immagini e contenuti HTML.

Quindi l'approccio alternativo non è quello di inviare il tipo MIME nella risposta. In questo modo il browser non saprà mai quale plug-in dovrebbe aprirlo. Quindi ti darà una finestra di dialogo Salva / Apri .


È difficile da ottenere perché è il server che invia il tipo mime e quando si collega direttamente a un file PDF, non è possibile modificare le intestazioni.
Karel Petranek,

0

Ho appena avuto un problema molto simile con il problema aggiunto di cui avevo bisogno per creare collegamenti di download ai file all'interno di un file ZIP.

Prima ho provato a creare un file temporaneo, quindi ho fornito un collegamento al file temporaneo, ma ho scoperto che alcuni browser avrebbero semplicemente visualizzato il contenuto (un file CSV Excel) anziché offrire il download. Alla fine ho trovato la soluzione usando un servlet. Funziona sia su Tomcat che su GlassFish e l'ho provato su Internet Explorer 10 e Chrome.

Il servlet prende come input un nome percorso completo per il file ZIP e il nome del file all'interno dello zip che deve essere scaricato.

All'interno del mio file JSP ho una tabella che mostra tutti i file all'interno dello zip, con collegamenti che dicono: onclick='download?zip=<%=zip%>&csv=<%=csv%>'

Il codice servlet è in download.java:

package myServlet;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.zip.*;
import java.util.*;

// Extend HttpServlet class
public class download extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException
    {
        PrintWriter out = response.getWriter(); // now we can write to the client

        String filename = request.getParameter("csv");
        String zipfile = request.getParameter("zip");

        String aLine = "";

        response.setContentType("application/x-download");
        response.setHeader( "Content-Disposition", "attachment; filename=" + filename); // Force 'save-as'
        ZipFile zip = new ZipFile(zipfile);
        for (Enumeration e = zip.entries(); e.hasMoreElements();) {
            ZipEntry entry = (ZipEntry) e.nextElement();
            if(entry.toString().equals(filename)) {
                InputStream is = zip.getInputStream(entry);
                BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"), 65536);
                while ((aLine = br.readLine()) != null) {
                    out.println(aLine);
                }
                is.close();
                break;
            }
        }
    }
}

Per compilare su Tomcat è necessario che il percorso di classe includa tomcat \ lib \ servlet-api.jar o su GlassFish: glassfish \ lib \ j2ee.jar

Ma uno dei due funzionerà su entrambi. È inoltre necessario impostare il servlet web.xml.


0

Aggiungi un'intestazione di risposta Disposizione-contenuto: allegato; seguito dal nome del file. Rimuovere la Meta Content-Disposition; Inline; che aprirà il documento nella stessa finestra

In java è impostato come

response.setHeader("Content-Disposition", "attachment;filename=test.jpg");

-2

Con file PDF di grandi dimensioni il browser si blocca. In Mozilla, menu StrumentiOpzioniApplicazioni , quindi accanto al tipo di contenuto documento Adobe Acrobat. Nel menu a discesa Azione, seleziona Chiedi sempre .

Questo non ha funzionato per me, quindi quello che ha funzionato è stato:

Strumenti menu * → Componenti aggiuntiviAdobe Acrobat (plug-in Adobe PDF per Firefox) → DISABLE. Ora sono in grado di scaricare e-book!


2
hai letto la domanda? questa non è una risposta cross-browser
Segna l'

1
@mark è anche istruzioni per un utente di richiedere download forzati di PDF, non un proprietario di un sito web.
Nathan Hornby,
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.