Metin bağlantısında "Farklı Kaydet ..." açılır penceresini açmaya zorla HTML'de PDF için tıklayın


173

Web sitemde bazı büyük boyutlu PDF kataloglarım var ve bunları indirme olarak bağlamam gerekiyor. Google'a gittiğimde aşağıda belirtilen bir şey buldum. Bağlantı tıklandığında " Farklı Kaydet ... " açılır penceresini açmalıdır ...

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

Ama işe yaramaz: / Aşağıdaki gibi bir dosyaya bağlandığımda, sadece dosyaya bağlanır ve dosyayı açmaya çalışır.

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

GÜNCELLEME (aşağıdaki cevaplara göre):

Gördüğüm gibi bunun için% 100 güvenilir bir çapraz tarayıcı çözümü yok. Muhtemelen en iyi yol, aşağıda listelenen web hizmetlerinden birini kullanmak ve bir indirme bağlantısı vermektir ...


1
pdf dosyaları için mime türünü sunmayın.
bhups

Güncellenmiş çözümünüzü denedim, artmania - ama Safari'de yaşadığım aynı sorun oluştu. Tarayıcı penceresindeki PDF'ye benzeyen şeyi alıyorum ve sadece alttaki "önizleme" veya "indir" sekmelerini tıkladığımda çok ihtiyaç duyduğum arama özelliğini alıyorum.
heathwaller


Yanıtlar:


267

Bir yanıttan tarayıcıyı, bağlantıyı tıkladıktan sonra olduğu gibi dosyayı kaydetmeye zorla :

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

17
Bu yorum sırasında, downloadözellik Chrome, Firefox ve Opera ile sınırlıdır. IE ve Safari'nin son sürümleri bile bunu desteklemiyor. Gelecekteki destek için: caniuse.com/#feat=download ! Adresini ziyaret edin !
Sygmoral

Netbeans hata kontrolü bu konuda şikayetçi, ama iyi çalışıyor gibi görünüyor. Yeni dosya için şu şekilde bir ön ad belirtebilirsiniz: download = "myFile.txt"
Yster

1
Bu, bu yorumu yazarken Edge'de çalışır ve Edge'in PDF görüntüleyicideki çok zayıf girişiminde açılmasını sağlayan köprülü PDF'leri durdurmanın tek yolu gibi görünüyor.

Bu yorum sırasında, Chrome, Opera, Edge, Mozilla'da test ettim. En son. Mozilla hariç her şey üzerinde çalışıyor.
SI

7
Bu yalnızca caniuse.com/#feat=download adresinde belirtildiği gibi aynı kaynaklı bağlantılar için geçerlidir . Bağlantılarınız çapraz kaynaksa, tek seçeneğiniz (şimdilik) yanıt türünü birçok yanıtın önerdiği gibi "application / octet-stream" e zorlamaktır. Sunucuya erişiminiz yoksa, proxy'ye bağlanmayı ve yanıt başlığını el ile ayarlamayı deneyebilirsiniz.
jean-baptiste

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

Firefox ve Chrome'da benim için çalışıyor.


2
Yine de, 2013'teki Ayush Gupta'dan mevcut en iyi cevapla aynı. Bu target="_blank", desteklemeyen tarayıcılar için biraz daha kullanılabilir hale getirebilir (PDF'ler geçerli sayfanın üzerine yazmak yerine yeni bir pencerede / sekmede açılır).
Sygmoral

3
Benim target="_blank"için gerekliydi downloadsadece indirmeyi düzgün bir şekilde tetikleyemedi (Chrome)
casraf

2
downloadÖznitelikte bir dize verirseniz , dosya adı olarak kullanılır. Ben her zaman userscripts kullanıyorum.
weaknespase

34

Meta etiketler bu sonuca ulaşmanın güvenilir bir yolu değildir. Genellikle bunu yapmamalısınız - sağladığınız içerikle ne yapacağınıza karar vermek kullanıcı / kullanıcı temsilcisine bırakılmalıdır. Kullanıcı isterse tarayıcısını her zaman dosyayı indirmeye zorlayabilir.

Hala tarayıcıyı dosyayı indirmeye zorlamak istiyorsanız, HTTP üstbilgilerini doğrudan değiştirin. İşte bir PHP kodu örneği:

$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

Bunun sadece HTTP protokolünün bir uzantısı olduğunu unutmayın; bazı tarayıcılar yine de yok sayabilir.


4
Uygulamada bunun yaygın olarak uygulandığına inanıyorum.
Matthew Wilson

Bu en iyi çözüm, sorunsuz ve çalışıyor. Bu yöntemi kullanarak herhangi bir dosya türünü doğrudan indirebilirsiniz. +1
casraf

3
HTTP'de Content-Transfer-Encoding mevcut değil. İçerik Kodlaması: hiçbiri işe yaramaz.
Julian Reschke

Cevabınızda bir NOT yapın, IF dosyası harici sunucudan / etki alanından
geliyorsa

Ben dosyaları büyük olduğunda (veya benim durumumda> 80 MB) bu ya da benzer kod bazı sunucularda başarısız olduğunu eklemek istiyorum. Kullanmak ob_end_flush()da yardımcı olmadı.
Hendrik

22

Aynı sorunu yaşadım ve şimdiye kadar harika çalışan bir çözüm buldum. .htaccessDosyanıza aşağıdaki kodu koydunuz :

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

Tarayıcıda Göstermek Yerine Dosyayı Yüklemeye Zorla'dan geldi .


4
İndirmeler için belirli bir belge dizinim olduğu için bu iyi çalıştı. ForceType'ı atladım, sadece türlerin olduğu gibi kalmasına izin verdim. Ayrıca büyük / küçük harfe duyarlı olmama gerek kalmadı; benimki zaten büyük / küçük harfe duyarsız görünüyor. Eski / yeni Office uzantıları için isteğe bağlı-x dahil olmak üzere birkaç tür daha ekledim:<FilesMatch "\.(pdf|xlsx?|docx?)$">
goodeye

Bu, diğer cevapların (kabul edilenler dahil, bir yorumcunun işaret ettiği gibi) verilen HTML özelliğini destekleyen belirli tarayıcılarla sınırlı olduğu OSX Safari'de bile harika çalıştı. Sunucu yapılandırma dosyalarına daha yüksek düzeyde erişim gerektirmesine rağmen, bu kartta çalıştığı için benim için daha ideal görünüyor.
bwright

Bunu apache.conf dosyanıza da koyabilirsiniz, daha fazla kaynak gerektirdiğinden .htaccess kullanmıyorum.
Michael Fever

Windows tarafından barındırılan bir web sitesi, htaccess dosyalarını okuyamadıkları için bunu nasıl uygular?
PoloHoleSet

9

Firefox için çok basit bir çözüm buldum (yalnızca doğrudan bir href yerine bir akraba ile çalışır): ekle type="application/octet-stream":

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

1
@ Chrome OS'de Chrome ve Linux'ta Firefox. Çalışması için dosyanın yerel olması gerektiği ortaya çıktı. Benim href bulut depolama için bir url oldu.
ttfreeman

7

Bu satırı .htaccess dosyanıza eklemeyi deneyin.

AddType application/octet-stream .pdf

Umarım tarayıcıdan bağımsız olduğu için çalışır.


Bunun neden indirildiğini bilmek isterim - en basit yöntemlerden ve çalışmalardan biri: css-tricks.com/snippets/htaccess/…
Nathan Hornby

İnsanlar ücretsiz barındırma sitelerinde bir sunucunun temel işlevselliğini değiştirmeye çalışırlar ve daha sonra çalışamazlar. Diğer tüm çözümlerde uyarılar olacaktır, çünkü bunun yerini almak bir "hacktir".
Terk Edilmiş Sepet

Sorunu azaltıyorum çünkü bu sorunun yanlış çözümü. Kaynak türlerini karıştırmak kötü bir fikirdir.
Brad

@NathanHornby - Ben aşağı itmedim, ama .htaccess kullanmadığı için bu herhangi bir Windows barındırılan site için işe yaramaz.
PoloHoleSet

Ben aldatmadım, ama bu çözüm körü körüne bu soneki TÜM dosyaları etkiler. Bu gelişigüzel ve bu nedenle her durumda uygun olmayacak.
JBH

6

Genellikle bu olur, çünkü bazı tarayıcı ayarları veya eklentileri PDF'yi basit bir web sayfası gibi aynı pencerede doğrudan açar.

Aşağıdakiler size yardımcı olabilir. Birkaç yıl önce PHP'de yaptım. Ama şu anda bu platform üzerinde çalışmıyorum.

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

Yukarıdakileri download.php kaydedin .

Bu küçük snippet'i sunucunuzun herhangi bir yerinde bir PHP dosyası olarak kaydedin ve doğrudan görüntülemek yerine tarayıcıda bir dosya indirmek için kullanabilirsiniz. PDF dışındaki dosyaları sunmak istiyorsanız 5. satırı kaldırın veya düzenleyin.

Şöyle kullanabilirsiniz:

HTML dosyanıza aşağıdaki bağlantıyı ekleyin.

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

Referans kaynağı: Bu blog


7
Bu, sunucunuzdaki her dosyayı dikkat eden herkese sunmak için iyi bir yol gibi görünüyor. download.php?file=database_password_file.phpÖrneğin.
pbarney

5

Aşağıdaki kodu .htaccessdosyanıza eklemeniz yeterlidir:

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

Veya JavaScript ile hile de yapabilirsiniz

element.setAttribute( 'download', whatever_string_you_want);

1
Bu web sunucusunun Apache olduğunu düşünmüyor mu?
Peter Mortensen

5

Bunu sadece kullandım, ancak tüm tarayıcılarda çalışıp çalışmadığını bilmiyorum.

Firefox'ta çalışır:

<a href="myfile.pdf" download>Click to Download</a>

1
Bu, daha önceki bir cevapta ve daha fazla arka plan bilgisi ile önerilir .
usr2564301

4

Bir gerçekten basit bir yolu harici indirme sitelerini kullanarak veya basitçe ZIP dosyası PDF iç ve doğrudan bağlantısını içeren bir ZIP dosyası oluşturmaktır vb başlıklarını değiştirmeden, bunu başarmak için. Bu, HER ZAMAN Kaydet / Aç iletişim kutusunu tetikler ve insanların .zip ile ilişkili programın PDF pencerelerini çift tıklatmaları yine de kolaydır.

BTW harika bir soru, ben de bir cevap arıyordum, çünkü çoğu tarayıcı gömülü PDF eklentisi herhangi bir şeyi görüntülemek için çok uzun sürüyor (ve PDF yüklenirken genellikle tarayıcıyı asacak).


31
Korkunç kullanılabilirlik. Birçok son kullanıcı bir zip dosyasıyla ne yapacağını bilemez.
CodeWarrior

1
Bazen basit çözümler en iyi çözümlerdir!
elrado

1
İyi bir çözüm değil. Firefox ve ZIP dosyası ile tam olarak bu problemim var. Ne yapmalıyım? ZIP dosyası? Bu durumda, HTTP üstbilgilerini değiştirmek bir çözüm olabilir, ancak buna erişimim yok.
Arnaud Weil

2

Bir sunucu tarafı çözümü, tüm tarayıcılara "indir" özelliği uygulanana kadar daha uyumludur.

Bir Python örneği, bir dosya deposu için özel bir HTTP istek işleyicisi olabilir. Dosya deposuna işaret eden bağlantılar şu şekilde oluşturulur:

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

İşte kod:

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

Sayfanızdaki tek bir bağlantı için indirmeyi zorlamanız gerekiyorsa, bunu yapmanın çok kolay bir yolu, href bağlantısında HTML5 indirme özelliğini kullanmaktır.

Bkz. Http://davidwalsh.name/download-attribute

bununla kullanıcının indireceği dosyayı yeniden adlandırabilir ve aynı zamanda indirmeye zorlayabilirsiniz.

Bunun iyi bir uygulama olup olmadığı konusunda bir tartışma var, ancak benim durumumda bir PDF dosyası için gömülü bir görüntüleyicim var ve görüntüleyici bir indirme bağlantısı sunmuyor, bu yüzden ayrı bir tane sağlamak zorundayım. Burada kullanıcının PDF'yi web tarayıcısında açmamasını sağlamak istiyorum, bu da kafa karıştırıcı olacaktır.

Bu, farklı kaydet iletişim kutusunu açmanıza gerek yoktur, ancak bağlantıyı doğrudan önceden ayarlanmış indirme hedefine indirir. Ve elbette başka biri için bir site yapıyorsanız ve bağlantılarına elle öznitelikler yazmaları gerekiyorsa, muhtemelen kötü bir fikirdir, ancak öznitelikleri bağlantılara almanın bir yolu varsa, bu hafif bir çözüm olabilir.


1

Bu eski yazı ama burada JavaScript benim çözüm ne jQuery kütüphane kullanarak.

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

Yalnızca etiketinizin force-downloadiçinde sınıf kullanmanız gerekir <a>ve indirme işlemini otomatik olarak zorlar. Ayrıca üst divöğeye ekleyebilirsiniz ve içindeki tüm bağlantıları alırsınız .

Misal:

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

Bu, WordPress ve diğer sistemler veya özel web siteleri için mükemmeldir.


0

HTML kodundaki dosya adından sonra ?forcedownload=1

Bu, kaydetmek veya indirmek için bir iletişim kutusunu tetiklemem için en basit yol oldu.


0

Tarayıcıda bir PDF dosyasının nasıl açılacağını bilen bir eklentiniz varsa doğrudan açılır. Resim ve HTML içeriğinde olduğu gibi.

Dolayısıyla alternatif yaklaşım, yanıtta MIME türünüzü göndermemektir. Bu şekilde tarayıcı hangi eklentiyi açması gerektiğini asla bilemez. Bu nedenle size bir Kaydet / Aç iletişim kutusu verecektir .


Mime türünü gönderen sunucu olduğundan ve doğrudan bir PDF dosyasına bağlanırken başlıkları değiştiremezsiniz, çünkü bunu başarmak zordur.
Karel Petranek

0

Ben sadece ZIP dosyası içindeki dosyalara indirme bağlantıları oluşturmak için gereken ek sorun ile çok benzer bir sorun vardı.

Önce geçici bir dosya oluşturmaya çalıştım, sonra geçici dosyaya bir bağlantı sağladım, ancak bazı tarayıcıların indirmeyi teklif etmek yerine içeriği (CSV Excel dosyası) göstereceğini buldum. Sonunda bir sunucu uygulaması kullanarak çözümü buldum. Hem Tomcat hem de GlassFish üzerinde çalışıyor ve Internet Explorer 10 ve Chrome'da denedim.

Sunucu uygulaması, girdi olarak ZIP dosyasına bir tam yol adı ve zip içinde indirilmesi gereken dosyanın adını alır.

JSP dosyamın içinde zip içindeki tüm dosyaları görüntüleyen bir tablo var. onclick='download?zip=<%=zip%>&csv=<%=csv%>'

Sunucu uygulaması kodu download.java'da:

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

Tomcat'te derlemek için sınıf yoluna tomcat \ lib \ servlet-api.jar veya GlassFish: glassfish \ lib \ j2ee.jar yazmanız gerekir

Ama ikisinden biri her ikisinde de çalışacaktır. Ayrıca sunucu uygulamanızı ayarlamanız gerekir web.xml.


0

Yanıt başlığı ekleyin Content-Disposition: attachment; ardından dosya adı. Meta İçeriği Kaldırma - Satır İçi; bu belgeyi aynı pencerede açar

Java'da şu şekilde ayarlanır:

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

-2

Büyük PDF dosyalarında tarayıcı kilitlenir. Mozilla'da, AraçlarSeçeneklerUygulamalar menüsünü ve ardından Adobe Acrobat belgesi içerik türünün yanındaki menüsünü kullanın. Eylem açılır menüsünde Her zaman sor'u seçin .

Bu benim için işe yaramadı, bu yüzden işe yarayan şuydu:

Menü Araçları * → EklentilerAdobe Acrobat (Firefox için Adobe PDF eklentisi) → DEVRE DIŞI BIRAK. Şimdi e-kitap indirebiliyorum!


2
soruyu okudun mu Bu bir çapraz tarayıcı yanıtı değil
Mark 8

1
@mark ayrıca, bir web sitesi sahibi değil, kullanıcının zorla PDF indirmesini istemesi için talimatlar içerir.
Nathan Hornby
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.