PDF dosyası HTML linkinde nasıl indirilebilir hale getirilir?


124

Aşağıdaki gibi indirilmek üzere web sayfamda bir pdf dosyasının bağlantısını veriyorum

<a href="myfile.pdf">Download Brochure</a>

Sorun, kullanıcı bu bağlantıyı tıkladığında

  • Kullanıcı Adobe Acrobat'ı yüklediyse, dosyayı Adobe Reader'da aynı tarayıcı penceresinde açar.
  • Adobe Acrobat kurulu değilse, dosyayı indirmek için kullanıcıya açılır.

Ancak, "Adobe acrobat" kurulu olup olmadığına bakılmaksızın, her zaman kullanıcının indirmesi için açılır olmasını istiyorum.

Lütfen bana bunu nasıl yapabileceğimi söyle?

Yanıtlar:


116

.PDF dosyasına bağlanmak yerine, bunun yerine aşağıdaki gibi bir şey yapın:

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

özel bir başlık çıkarır, PDF'yi açar (ikili kasa) ve verileri kullanıcının tarayıcısına yazdırır, ardından tarayıcı ayarlarına rağmen PDF'yi kaydetmeyi seçebilirler. Pdf_server.php şu şekilde görünmelidir:

header("Content-Type: application/octet-stream");

$file = $_GET["file"] .".pdf";
header("Content-Disposition: attachment; filename=" . urlencode($file));   
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); 

Not: ve insanların dosyalarınızı çalmasını önlemek için "dosya" değişkeninde dosya uzantılarını kabul etmeme, eğik çizgileri reddetme, değere .pdf ekleme gibi bazı mantıklı kontroller çalıştırın.


2
Bununla ilgili başka bir sorunla karşı karşıyayım, dosyam /products/brochure/myfile.pdf konumunda bulunuyor. $ Dosya değişkenini $ file_path = $ _SERVER ['DOCUMENT_ROOT'] olarak veriyorum. '/ Products / broşür /'. Dosyayı, $; ancak dosyayı "% 2Fvar% 2Fwww% 2Fweb15% 2Fweb% 2Fproducts% 2Fbrochure% 2myfile.pdf" olarak indiriyor
Prashant

3
@TravisO "Content-type: application/force-download"burada herhangi bir yerde listelenmemiştir: iana.org/assignments/media-types/application Tamamen sahte bir başlıktır. Lütfen başlıklar oluşturup göndermeyin. Cevabınızı günceller misiniz? Teşekkürler.
Nicholas Wilson

4
Yine de bu kodu kelimesi kelimesine kullanırken dikkatli olun. Bu, GET değişkenlerini doğrudan içine geçirdiğiniz için ciddi bir LFI güvenlik açığı ortaya çıkarır fopen.
Joost

4
Bu kod başka bir şekilde muhtemelen tehlikelidir. HTTP bağlantılarını fopen'a iletirseniz, dosyayı başka bir sunucudan alacağını düşünüyorum. Bir saldırgan tarafından iç ağınızda açıkta kalan PDF dosyalarını taramaya çalışmak için kullanılabilir.
Rory McCune

2
"File" parametresine yapacağınızı düşündüğünüz "mantıklı kontrolleri" atlamanın ne kadar kolay olacağından bahsetmiyorum bile. Yol enjeksiyonu / dizin geçişi saldırıları oldukça olasıdır.
AviD

210

Bu yaygın bir sorundur, ancak çok az kişi basit bir HTML 5 çözümü olduğunu bilir:

<a href="./directory/yourfile.pdf" download="newfilename">Download the pdf</a>

newfilenameKullanıcının dosyayı kaydetmesi için önerilen dosya adı nerede . Veya boş bırakırsanız, sunucu tarafındaki dosya adını şu şekilde varsayılan olarak atar:

<a href="./directory/yourfile.pdf" download>Download the pdf</a>

Uyumluluk: Bunu Firefox 21 ve Iron'da test ettim, ikisi de iyi çalıştı. HTML5 uyumlu olmayan veya eski tarayıcılarda çalışmayabilir. İndirmeye zorlamayan test ettiğim tek tarayıcı IE ...

Uyumluluğu buradan kontrol edin: http://caniuse.com/#feat=download


9
Bu basit bir çözüm, ancak maalesef çok yaygın olarak desteklenmiyor, özellikle. IE tarafından desteklenmiyor caniuse.com/#feat=download
benebun

2
Evet, doğru biliyorum. Bu yüzden uyumlulukla ilgili yan notum var. Ve kaynağınıza göre, hem IE hem de Safari bu yaklaşımı desteklemiyor veya en azından henüz değil :) Her neyse, tüm tarayıcıların indirmeye zorlamasını istiyorsanız, bunun yerine diğer yanıtlardan bazılarını kontrol
etmenizi öneririm

3
Chrome Sürüm 39.0.2171.65 (64-bit) ile bir cazibe gibi çalışır!
edelans

Çözüm kolaydır, ancak ne yazık ki IE ve Safari'de desteklenmemektedir.
valkirilov

erişim izni yok diyor
Hackbal Teamz

50

Her dosya satırında döngü yapmayın . Kullanım readfile onun daha hızlı yerine. Bu php sitesi dışındadır: http://php.net/manual/en/function.readfile.php

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

Birisi bazı php dosyalarını indirebileceği için get değişkeninizi temizlediğinizden emin olun ...


4
Readfile fonksiyon gerçekten hızlıdır. Kabul edilen yanıt yerine bu yanıtı kullanmanızı kişisel olarak tavsiye ediyorum
Jose Garrido

24

Bir PHP betiği kullanmak yerine, dosyayı okumak ve temizlemek için, başlığı kullanarak yeniden yazmak daha temizdir .htaccess. Bu, ( myfile.pdfyerine download.php?myfile) "güzel" bir URL tutacaktır .

<FilesMatch "\.pdf$">
ForceType applicaton/octet-stream
Header set Content-Disposition attachment
</FilesMatch>

Bu, TÜM PDF'lerinizin zorla indirilmesini sağlamaz mı?
TecBrat

1
@TecBrat Evet, ama OP'nin sorduğu buydu. Yalnızca birkaç PDF ile sınırlamak istiyorsanız, ^\.pdf$normal ifadeyi düzenleyin .
Rob W

1
@TecBrat veya .htaccess dosyasını yalnızca bu davranışın gerekli olduğu alt klasöre koyun.
habakuk

14

Düzgün eski HTML ve JavaScript / jQuery ile yapmanın bir yolunu buldum, bu da zarif bir şekilde bozuldu. IE7-10, Safari, Chrome ve FF'de test edilmiştir:

İndirme bağlantısı için HTML:

<p>Thanks for downloading! If your download doesn't start shortly, 
<a id="downloadLink" href="...yourpdf.pdf" target="_blank" 
type="application/octet-stream" download="yourpdf.pdf">click here</a>.</p>

Küçük bir gecikmeden sonra bağlantıya tıklamayı simüle eden jQuery (saf JavaScript kodu daha ayrıntılı olacaktır):

var delay = 3000;
window.setTimeout(function(){$('#downloadLink')[0].click();},delay);

Bunu daha sağlam hale getirmek için, HTML5 özellik algılaması ekleyebilir ve orada değilse window.open(), dosyayla yeni bir pencere açmak için kullanabilirsiniz .


5

Anahtar bu:

header("Content-Type: application/octet-stream");

PDF dosyası gönderilirken içerik tipi application / x-pdf-document veya application / pdf gönderilir. Adobe Reader genellikle bu MIME türü için işleyiciyi ayarlar, böylece tarayıcı belgeyi PDF MIME türlerinden herhangi biri alındığında Adobe Reader'a iletir.


3

Bunu cevaplamak için çok geç kaldığımı biliyorum ama bunu javascript'te yapmak için bir hack buldum.

function downloadFile(src){
    var link=document.createElement('a');
    document.body.appendChild(link);
    link.href= src;
    link.download = '';
    link.click();
}

0

Bunu dene:

<a href="pdf_server_with_path.php?file=pdffilename&path=http://myurl.com/mypath/">Download my eBook</a>

Pdf_server_with_path.php içindeki kod:

header("Content-Type: application/octet-stream");

$file = $_GET["file"] .".pdf";
$path = $_GET["path"];
$fullfile = $path.$file;

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($fullfile));
flush(); // this doesn't really matter.
$fp = fopen($fullfile, "r");
while (!feof($fp))
{
    echo fread($fp, 65536);
    flush(); // this is essential for large downloads
} 
fclose($fp);

0

İşte farklı bir yaklaşım. Web sunucusu mantığını kullanmak için tarayıcı desteğine güvenmeyi veya bunu uygulama katmanında ele almayı tercih ederim.

Apache kullanıyorsanız ve ilgili dizine bir .htaccess dosyası koyabiliyorsanız, aşağıdaki kodu kullanabilirsiniz. Elbette, buna erişiminiz varsa, bunu httpd.conf'a da koyabilirsiniz.

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

FilesMatch yönergesi sadece bir normal ifadedir, bu nedenle istediğiniz kadar parçalı olarak ayarlanabilir veya başka uzantılar ekleyebilirsiniz.

Başlık satırı, yukarıdaki PHP komut dosyalarındaki ilk satırla aynı şeyi yapar. İçerik Türü satırlarını da ayarlamanız gerekiyorsa, bunu aynı şekilde yapabilirsiniz, ancak bunu gerekli bulmadım.


0

PDF dosyasının tüm url'sini kullanarak benimkini çözdüm (sadece dosya adını veya konumunu href'e koymak yerine): a href = "domain. Com / pdf / dosyaadı.pdf"


0

indirme oranını sınırlamanız gerekiyorsa bu kodu kullanın !!

<?php
$local_file = 'file.zip';
$download_file = 'name.zip';

// set the download rate limit (=> 20,5 kb/s)
$download_rate = 20.5;
if(file_exists($local_file) && is_file($local_file))
{
header('Cache-control: private');
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($local_file));
header('Content-Disposition: filename='.$download_file);

flush();
$file = fopen($local_file, "r");
while(!feof($file))
{
    // send the current file part to the browser
    print fread($file, round($download_rate * 1024));
    // flush the content to the browser
    flush();
    // sleep one second
    sleep(1);
}
fclose($file);}
else {
die('Error: The file '.$local_file.' does not exist!');
}

?>

Daha fazla bilgi için buraya tıklayın


0
<!DOCTYPE html>  
<html xmlns="http://www.w3.org/1999/xhtml">  
<head>  
    <title>File Uploader</title>  
    <script src="../Script/angular1.3.8.js"></script>  
    <script src="../Script/angular-route.js"></script>  
    <script src="../UserScript/MyApp.js"></script>  
    <script src="../UserScript/FileUploder.js"></script>  
    <>  
        .percent {  
            position: absolute;  
            width: 300px;  
            height: 14px;  
            z-index: 1;  
            text-align: center;  
            font-size: 0.8em;  
            color: white;  
        }  

        .progress-bar {  
            width: 300px;  
            height: 14px;  
            border-radius: 10px;  
            border: 1px solid #CCC;  
            background-image: -webkit-gradient(linear, left top, left bottom, from(#6666cc), to(#4b4b95));  
            border-image: initial;  
        }  

        .uploaded {  
            padding: 0;  
            height: 14px;  
            border-radius: 10px;  
            background-image: -webkit-gradient(linear, left top, left bottom, from(#66cc00), to(#4b9500));  
            border-image: initial;  
        }  
    </>  
</head>  
<body ng-app="MyApp" ng-controller="FileUploder">  
    <div>  
        <table ="width:100%;border:solid;">  
            <tr>  
                <td>Select File</td>  
                <td>  
                    <input type="file" ng-model-instant id="fileToUpload" onchange="angular.element(this).scope().setFiles(this)" />  
                </td>  
            </tr>  
            <tr>  
                <td>File Size</td>  
                <td>  
                    <div ng-repeat="file in files.slice(0)">  
                        <span ng-switch="file.size > 1024*1024">  
                            <span ng-switch-when="true">{{file.size / 1024 / 1024 | number:2}} MB</span>  
                            <span ng-switch-default>{{file.size / 1024 | number:2}} kB</span>  
                        </span>  
                    </div>  
                </td>  
            </tr>             
            <tr>  
                <td>  
                    File Attach Status  
                </td>  
                <td>{{AttachStatus}}</td>  
            </tr>  
            <tr>  
                <td>  
                    <input type="button" value="Upload" ng-click="fnUpload();" />  
                </td>  
                <td>  
                    <input type="button" value="DownLoad" ng-click="fnDownLoad();" />  
                </td>  
            </tr>  
        </table>  
    </div>  
</body>  
</html>   

1
Kodunuzda ne sağladığınızı açıklamalısınız. Ayrıntılı olarak mümkün değilse veya detaylarda gerekli değilse kısa formda bile.
Suraj Kumar

-1

Bir Ruby on Rails uygulamasında (özellikle Prawn mücevher ve Prawnto Rails eklentisi gibi bir şeyle), bunu tam bir komut dosyasından biraz daha basit bir şekilde gerçekleştirebilirsiniz (önceki PHP örneği gibi).

Denetleyicinizde:

def index

 respond_to do |format|
   format.html # Your HTML view
   format.pdf { render :layout => false }
 end
end

Render: layout => false bölümü, tarayıcıya "Bu dosyayı indirmek ister misiniz?" PDF'yi oluşturmaya çalışmak yerine komut istemi. Ardından dosyaya normal şekilde bağlanabilirsiniz: http://mysite.com/myawesomepdf.pdf


Bu kodu nereye yazmalı? hangi denetleyici, PHP'de yeniyim lütfen açıklayın.
Prashant

@Prashant Bu PHP değil, Ruby on Rails.
eloyesp

@Prashant: Bir PHP örneğine ihtiyacınız varsa, iş parçacığının ilerleyen kısımlarına bakın, ancak lütfen nasıl güvensiz olabileceğiyle ilgili yorumları okuyun.
Evan Donovan
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.