Paksa membuka "Simpan Sebagai ..." yang terbuka di tautan teks klik untuk PDF dalam HTML

173

Saya memiliki beberapa katalog PDF ukuran besar di situs web saya, dan saya perlu menautkan ini sebagai unduhan. Ketika saya mencari di Google, saya menemukan hal seperti itu di bawah ini. Seharusnya membuka munculan " Simpan Sebagai ... " di tautan klik ...

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

Tapi itu tidak berfungsi: / Ketika saya menautkan ke file seperti di bawah ini, itu hanya menautkan ke file dan sedang mencoba untuk membuka file.

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

UPDATE (sesuai dengan jawaban di bawah):

Seperti yang saya lihat tidak ada solusi lintas-browser 100% andal untuk ini. Mungkin cara terbaik adalah menggunakan salah satu layanan web yang tercantum di bawah ini, dan memberikan tautan unduh ...

desainer-mencoba-coding
sumber
1
jangan menayangkan mimetype untuk file pdf.
bhups
Saya mencoba solusi Anda yang diperbarui, artmania - tetapi masalah yang sama yang saya alami di Safari terjadi. Saya mendapatkan apa yang tampak seperti PDF di jendela browser, dan hanya ketika saya mengklik tab "pratinjau" atau "unduh" di bagian bawah saya mendapatkan fitur pencarian yang sangat saya butuhkan.
heathwaller
tanpa klik: stackoverflow.com/questions/2598658/…
Ciro Santilli 郝海东 冠状 病 六四 六四 事件
serupa tapi kurang jenis file tertentu: stackoverflow.com/questions/1465573/...
Ciro Santilli郝海东冠状病六四事件法轮功

Jawaban:

268

Dari jawaban untuk Memaksa browser untuk menyimpan file setelah mengeklik tautan :

<a href="path/to/file" download>Click here to download</a>
Ayush Gupta
sumber
17
Pada saat komentar ini, downloadatributnya terbatas pada Chrome, Firefox dan Opera. Bahkan versi terbaru dari IE dan Safari tidak mendukungnya. Untuk dukungan di masa mendatang: periksa caniuse.com/#feat=download !
Sygmoral
Memeriksa kesalahan Netbeans mengeluh tentang hal itu, tetapi tampaknya berfungsi dengan baik. Anda dapat menentukan nama awal untuk file baru seperti: unduh = "myFile.txt"
Yster
1
Ini berfungsi di Edge pada saat menulis komentar ini, dan sepertinya satu-satunya cara yang mungkin untuk menghentikan pembukaan tautan PDF yang hyperlink dalam upaya Edge yang sangat buruk pada penampil PDF.
Pada saat komentar ini, saya sudah mengujinya di Chrome, Opera, Edge, Mozilla. Semua terbaru. Sedang mengerjakan semua kecuali di Mozilla.
SI
7
Ini hanya bekerja untuk link yang sama-asal, seperti yang disebutkan di caniuse.com/#feat=download . Jika tautan Anda adalah lintas asal, satu-satunya pilihan Anda (untuk saat ini) adalah memaksa jenis respons ke "aliran aplikasi / octet", seperti yang disarankan oleh banyak jawaban. Jika Anda tidak memiliki akses ke server, maka Anda dapat mencoba proksi dan mengatur header respons secara manual.
jean-baptiste
81
<a href="file link" download target="_blank">Click here to download</a>

Ini berfungsi untuk saya di Firefox dan Chrome.

DrWaky
sumber
2
Namun persis sama dengan jawaban teratas saat ini, dari Ayush Gupta pada 2013. Namun, target="_blank"mungkin membuatnya sedikit lebih dapat digunakan untuk browser yang tidak mendukung, (PDF kemudian dibuka di jendela / tab baru, daripada menimpa halaman saat ini).
Sygmoral
3
Bagi saya, target="_blank"itu diperlukan karena downloadhanya gagal memicu unduhan dengan benar (Chrome)
casraf
2
Jika Anda memberikan string dalam downloadatribut, itu akan digunakan sebagai nama file. Saya menggunakannya dalam skrip pengguna sepanjang waktu.
titik lemah
34

Meta tag bukan cara yang andal untuk mencapai hasil ini. Umumnya Anda bahkan tidak boleh melakukan ini - itu harus diserahkan kepada pengguna / agen pengguna untuk memutuskan apa yang harus dilakukan dengan konten yang Anda berikan. Pengguna selalu dapat memaksa browser mereka untuk mengunduh file jika mereka mau.

Jika Anda masih ingin memaksa browser untuk mengunduh file, modifikasi header HTTP secara langsung. Berikut ini contoh kode 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

Perhatikan bahwa ini hanyalah perpanjangan dari protokol HTTP; beberapa browser mungkin mengabaikannya.

Karel Petranek
sumber
4
Dalam praktiknya saya percaya ini diterapkan secara luas.
Matthew Wilson
Ini adalah solusi terbaik, bebas repot dan berfungsi. Anda dapat langsung mengunduh jenis file apa pun menggunakan metode ini. +1
casraf
3
Content-Transfer-Encoding tidak ada di HTTP. Content-Encoding: tidak ada yang tidak berguna.
Julian Reschke
PASTIKAN jawaban Anda, bahwa file IF berasal dari server / domain eksternal, maka jawaban ini mungkin bukan solusi ...
T.Todua
Saya ingin menambahkan bahwa saya mengalami kegagalan ini atau kode serupa pada server tertentu ketika file menjadi besar (> 80 MB dalam kasus saya) Menggunakan ob_end_flush()juga tidak membantu.
Hendrik
22

Saya memiliki masalah yang sama dan menemukan solusi yang sejauh ini berhasil. Anda memasukkan kode berikut dalam .htaccessfile Anda :

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

Itu datang dari Paksa File untuk Diunduh bukannya Muncul di Browser .

Tony
sumber
4
Ini bekerja dengan baik, karena saya memiliki direktori dokumen tertentu untuk diunduh. Saya menghilangkan ForceType, hanya untuk membiarkan tipe tetap apa adanya. Saya juga tidak membutuhkan case-insensitive; punyaku sepertinya sudah peka terhadap huruf besar-kecil. Saya menambahkan beberapa jenis tambahan, termasuk opsional-x untuk ekstensi Office lama / baru:<FilesMatch "\.(pdf|xlsx?|docx?)$">
selamat tinggal
Ini bekerja luar biasa, bahkan di OSX Safari, di mana sebagai jawaban lain (termasuk yang diterima, seperti yang ditunjukkan oleh seorang komentator di sana) terbatas pada browser tertentu yang mendukung fitur HTML yang diberikan. Yang ini sepertinya lebih ideal bagi saya karena bekerja di seluruh papan, meskipun memang memerlukan akses tingkat tinggi ke file konfigurasi server.
bwright
Anda dapat meletakkannya di file apache.conf Anda juga, saya tidak menggunakan .htaccess karena membutuhkan lebih banyak sumber daya.
Michael Fever
Bagaimana situs web yang di-host oleh Windows menerapkan ini, karena mereka tidak dapat membaca file htaccess?
PoloHoleSet
10

Saya menemukan solusi yang sangat sederhana untuk Firefox (hanya bekerja dengan kerabat daripada href langsung): tambahkan type="application/octet-stream":

<a href="./file.pdf" id='example' type="application/octet-stream">Example</a>
Pengguna
sumber
1
@Martin Chrome di Chrome OS dan Firefox di Linux. Ternyata file tersebut harus lokal agar dapat berfungsi. Href saya adalah url ke penyimpanan cloud.
ttfreeman
7

Coba tambahkan baris ini ke file .htaccess Anda.

AddType application/octet-stream .pdf

Saya harap ini akan berfungsi karena ini adalah browser yang independen.

Sharad Gautam
sumber
Saya tertarik untuk mengetahui mengapa hal ini dibatalkan - ini salah satu metode dan karya paling sederhana: css-tricks.com/snippets/htaccess/…
Nathan Hornby
Orang-orang mencoba untuk memodifikasi fungsionalitas inti dari server di situs hosting gratis dan kemudian downvote karena mereka tidak dapat membuatnya berfungsi. Setiap solusi lain akan memiliki peringatan karena ini adalah "hack" untuk menggantikannya.
Abandoned Cart
Saya downvoting karena itu solusi yang salah untuk masalah ini. Itu ide yang buruk untuk mengacaukan jenis sumber daya.
Brad
@NathanHornby - Saya tidak melakukan downvote, tetapi ini tidak akan berfungsi untuk situs yang di-host Windows, karena mereka tidak menggunakan .htaccess.
PoloHoleSet
Saya tidak melakukan downvote, tetapi solusi ini secara membabi buta memengaruhi SEMUA file akhiran itu. Itu sembarangan dan karenanya tidak akan sesuai dalam semua kasus.
JBH
6

Umumnya itu terjadi, karena beberapa pengaturan browser atau plug-in langsung membuka PDF di jendela yang sama seperti halaman web sederhana.

Berikut ini mungkin membantu Anda. Saya sudah melakukannya di PHP beberapa tahun yang lalu. Tetapi saat ini saya tidak bekerja pada platform itu.

<?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>";
    }
?>

Simpan yang di atas sebagai download.php .

Simpan potongan kecil ini sebagai file PHP di suatu tempat di server Anda dan Anda dapat menggunakannya untuk membuat unduhan file di browser, daripada ditampilkan secara langsung. Jika Anda ingin menyajikan file selain PDF, hapus atau edit baris 5.

Anda dapat menggunakannya seperti ini:

Tambahkan tautan berikut ke file HTML Anda.

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

Referensi dari: Blog ini

Ashay
sumber
7
Tampaknya ini cara yang bagus untuk menyajikan setiap file di server Anda kepada siapa saja yang memperhatikan. download.php?file=database_password_file.phpsebagai contoh.
pbarney
5

Masukkan saja kode di bawah ini ke .htaccessfile Anda :

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

Atau Anda juga bisa melakukan trik dengan JavaScript

element.setAttribute( 'download', whatever_string_you_want);
manish1706
sumber
1
Bukankah ini menganggap server web adalah Apache ?
Peter Mortensen
5

Saya baru saja menggunakan ini, tetapi saya tidak tahu apakah itu berfungsi di semua browser.

Ini berfungsi di Firefox:

<a href="myfile.pdf" download>Click to Download</a>
SekarangLiveLove
sumber
1
Itu disarankan, dan dengan lebih banyak informasi latar belakang, dalam jawaban sebelumnya .
usr2564301
4

Cara yang sangat sederhana untuk mencapai hal ini, tanpa menggunakan situs unduhan eksternal atau memodifikasi tajuk dll adalah dengan hanya membuat file ZIP dengan PDF di dalamnya dan menautkan langsung ke file ZIP. Ini akan SELALU memicu dialog Simpan / Buka, dan masih mudah bagi orang untuk mengklik dua kali jendela PDF yang terkait dengan program .zip diluncurkan.

BTW pertanyaan yang bagus, saya mencari jawaban juga, karena sebagian besar plugin PDF yang disematkan oleh browser membutuhkan waktu lama untuk menampilkan apa pun (dan akan sering menggantung browser saat PDF sedang memuat).

Tuan Bungle
sumber
31
Kegunaan yang mengerikan. Banyak pengguna akhir tidak tahu apa yang harus dilakukan dengan file zip.
CodeWarrior
1
Terkadang solutioan sederhana adalah solusi terbaik!
elrado
1
Bukan solusi yang bagus. Saya memiliki masalah dengan Firefox dan file ZIP. Apa yang harus saya lakukan? Zip file? Dalam hal itu, memodifikasi header HTTP bisa menjadi solusi tetapi saya tidak memiliki akses ke sana.
Arnaud Weil
2

Solusi sisi server lebih kompatibel, hingga atribut "unduhan" diimplementasikan di semua browser.

Salah satu contoh Python bisa menjadi penangan permintaan HTTP khusus untuk filestore. Tautan yang mengarah ke filestore dihasilkan seperti ini:

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

Ini kodenya:

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()
Yucer
sumber
2

Cara yang sangat mudah untuk melakukan ini, jika Anda harus memaksa unduhan untuk satu tautan pada halaman Anda, adalah dengan menggunakan atribut unduhan HTML5 di href-link.

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

dengan ini Anda dapat mengganti nama file yang akan diunduh pengguna dan pada saat yang sama memaksa unduhan.

Ada perdebatan apakah ini praktik yang baik atau tidak, tetapi dalam kasus saya, saya memiliki penampil yang disematkan untuk file PDF dan penampil tidak menawarkan tautan unduhan, jadi saya harus menyediakannya secara terpisah. Di sini saya ingin memastikan pengguna tidak membuka PDF di browser web, yang akan membingungkan.

Ini tidak perlu membuka save as-dialog, tetapi akan mengunduh tautan langsung ke tujuan unduhan yang telah ditetapkan. Dan tentu saja jika Anda melakukan situs untuk orang lain, dan memerlukan mereka untuk menulis secara manual atribut ke tautan mereka mungkin merupakan ide yang buruk, tetapi jika ada cara untuk memasukkan atribut ke tautan, ini bisa menjadi solusi yang ringan.

JJxyz
sumber
1

Ini adalah posting lama tapi di sini adalah solusi saya dalam JavaScript apa yang menggunakan perpustakaan 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>

Anda hanya perlu menggunakan kelas force-downloaddi dalam <a>tag Anda dan akan memaksa unduhan secara otomatis. Anda juga dapat menambahkannya ke induk divdan akan mengambil semua tautan di dalamnya.

Contoh:

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

Ini bagus untuk WordPress dan sistem lain atau situs web khusus.

Ivijan Stefan Stipic
sumber
0

Setelah nama file dalam kode HTML saya tambahkan ?forcedownload=1

Ini adalah cara paling sederhana bagi saya untuk memicu kotak dialog untuk menyimpan atau mengunduh.

Bonnie
sumber
0

Jika Anda memiliki plugin di dalam browser yang tahu cara membuka file PDF, itu akan terbuka secara langsung. Seperti dalam hal gambar dan konten HTML.

Jadi pendekatan alternatifnya bukan mengirim tipe MIME Anda dalam respons. Dengan cara ini browser tidak akan pernah tahu plugin mana yang harus membukanya. Maka itu akan memberi Anda kotak dialog Simpan / Buka .

sushil bharwani
sumber
Itu sulit dicapai karena server yang mengirim tipe mime dan ketika menautkan langsung ke file PDF, Anda tidak dapat mengubah header.
Karel Petranek
0

Saya baru saja mengalami masalah yang sangat mirip dengan masalah tambahan yang saya butuhkan untuk membuat tautan unduhan ke file di dalam file ZIP.

Saya pertama kali mencoba membuat file sementara, kemudian memberikan tautan ke file sementara, tetapi saya menemukan bahwa beberapa browser hanya akan menampilkan konten (file CSV Excel) daripada menawarkan untuk mengunduh. Akhirnya saya menemukan solusinya dengan menggunakan servlet. Ini berfungsi baik pada Tomcat dan GlassFish, dan saya mencobanya di Internet Explorer 10 dan Chrome.

Servlet mengambil sebagai input nama path lengkap ke file ZIP, dan nama file di dalam zip yang harus diunduh.

Di dalam file JSP saya, saya punya tabel yang menampilkan semua file di dalam zip, dengan tautan yang mengatakan: onclick='download?zip=<%=zip%>&csv=<%=csv%>'

Kode servlet ada di 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;
            }
        }
    }
}

Untuk mengkompilasi pada Tomcat Anda memerlukan classpath untuk memasukkan tomcat \ lib \ servlet-api.jar atau di GlassFish: glassfish \ lib \ j2ee.jar

Tetapi salah satu akan bekerja pada keduanya. Anda juga perlu mengatur servlet Anda web.xml.

mljm
sumber
0

Tambahkan header respons Content-Disposition: attachment; diikuti oleh nama file. Hapus Meta Content-Disposition; Inline; yang akan membuka dokumen di jendela yang sama

Di java sudah diatur sebagai

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

Dengan file PDF besar, browser hang. Di Mozilla, menu AlatOpsiAplikasi , lalu di sebelah jenis konten dokumen Adobe Acrobat. Di menu tarik-turun Tindakan, pilih Selalu tanya .

Ini tidak berhasil untuk saya, jadi yang berhasil adalah:

Alat Menu * → PengayaAdobe Acrobat ( Pengaya Adobe PDF untuk Firefox) → DISABLE. Sekarang saya dapat mengunduh e-book!

Joojoo
sumber
2
apakah kamu membaca pertanyaan? ini bukan jawaban lintas peramban
Tandai
1
@ tandai itu juga petunjuk bagi pengguna untuk mendorong unduhan paksa PDF, bukan pemilik situs web.
Nathan Hornby