(HTML) Tıklandığında tarayıcıda açmak yerine bir PDF dosyası indirin


115

Tarayıcıda açmak yerine bir PDF dosyası bağlantısını nasıl indirilebilir hale getireceğimi merak ediyordum. Bu html'de nasıl yapılır? (Bunun javascript veya başka bir şeyle yapıldığını varsayıyorum).


3
Bu benim bildiğim kadarıyla kodlanabilen bir davranış değil. Çoğu tarayıcının, indirme sırasında belirli dosya türleriyle ne yapılacağına ilişkin kendi ayarları vardır.
Bart

1
HTML5'ten itibaren OP, Sarım'ın cevabına verilen doğru cevabı güncellemelidir.
Omar Tariq


Bu soru burada da yanıtlandı: stackoverflow.com/a/30714824/847235
intrepidis

Yanıtlar:


38

Bunu HTML ile yapamazsınız. Sunucu tabanlı bir çözümdür. Tarayıcının kaydetme iletişim kutusunu tetiklemesi için dosyayı akışa almalısınız.

Bunu yapmamayı tavsiye ederim. Bir kullanıcının bir PDF ile nasıl etkileşim kuracağı kullanıcıya bırakılmalıdır.

GÜNCELLEME (2014):

Yani ... bu cevap hala pek çok olumsuz oy alıyor. Sanırım bunun bir kısmı 4 yıl önce yanıtlanmıştı ve Sarım'ın da işaret ettiği gibi artık bunu halledebilecek HTML 5 downloadözelliği var.

Katılıyorum ve Sarım'ın cevabının iyi olduğunu düşünüyorum (OP geri dönerse muhtemelen seçilen cevap bu olmalıdır). Bununla birlikte, bu cevap hala onu ele almanın güvenilir yoludur (Yiğit Yener'in cevabının işaret ettiği ve - garip bir şekilde - insanlar aynı fikirde olduğu gibi). İndirme özelliği destek kazanmış olsa da, hala yetersiz:

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


18
Bunun bir yaşında olduğunu biliyorum - ama katılmıyorum. Bu davranışı zorlamanın uygulama akışı için çok önemli olduğu koşullar vardır. Asıl cevap, başlıktaki content-Disposition'ı "satır içi" yerine "ek" olarak ayarlamaktır.
user158017

9
Diğer durumlarda, bunu kullanıcı kontrolüne bırakmanın daha iyi olduğunu kabul ediyorum. Ancak, bu konuya bir cevap aramak için geldim ve kontrol edilen "cevap" bir cevap değildi - "bunu yapmamalısın" idi. Bana göre bu, sorunun cevabı değil. Bunun yerine, bir özel bir cevap ve ayrıca tavsiye.
user158017

1
Bazen soru yanlıştır. ;) Her neyse, sorununuzla ilgili olarak, hepsi bir UX sorunu. Web'i belirli şekillerde davranmaya zorlamak bazen gerekli olabilir, ancak genellikle kullanıcı deneyimi açısından daha iyi çözümler vardır. Ayrıca cevabım doğru. HTML ile yapmak istediğinizi yapamazsınız (soruyu soran da buydu). Sunucu tarafı çözümü olarak.
DA.

1
Bu şimdiye kadar yayınladığım en garip cevaplardan biri. İnsanlar hala burada olumsuz oy kullanmanın yolunu buluyor. Hangisi iyi! Ama nedenini bilmek ilginç olurdu.
DA.

3
Bu olumsuz oylamayla ilgili olarak, metinde istemeden kibirli görünmenin ne kadar kolay olduğu medeniyetin çöküşü olabilir . Bu cevap bana patronluk taslayan fikir ve cevaplar konusunda kısa sürdüğüm sürece beni etkiliyor. 1. paragraf yerine http, soruya etiketi eklemeniz yeterlidir. 2. paragraf yerine: "Hemen PDF görüntülemeyi engellemenin tüm kullanıcıların yararına olup olmadığını yeniden düşünmek isteyebilirsiniz. Bunu söyledikten sonra ..." O zaman, OP'nin ve gelecekteki okuyucuların yetişkin olduklarını ve Yener'in gibi uygulanabilir bir cevaba geçtiklerini varsayın. .
Bob Stein

133

Html5 ile artık mümkün. Öğesinde bir "indirme" özelliği ayarlayın.

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

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


Destekleniyorsa bu çözüme gitseniz iyi olur. İşte olup olmadığını kontrol etmenin bir yoluif ("download" in document.createElement("a")){ ... }
pmrotule

Aşağıya başka bir cevap ekledim (kötü hack), yine de tercih edilen yol bu olsa da, belki hack yolu desteklenmeyen tarayıcılar için sunulabilir.
Sarım

Dosya yolundan bahsetmek yerine pdf metnini belirtmenin bir yolu var mı? Bir div
html'den

1
Şu anda Ağustos 2019, bu özellik için Tarayıcı desteği geliştirilmiş görünüyor, bkz: w3schools.com/tags/att_a_download.asp
Daniel Resch

2
İndirme özniteliğinin yalnızca aynı kaynaklı istekler için desteklendiğini unutmayın.
Quentin

82

Bu, yalnızca sunucu tarafı koduyla bir http yanıt başlığının ayarlanmasıyla mümkündür. Yani;

Content-Disposition: attachment; filename=fname.ext

2
bu mükemmel bir cevap - bunu uygun sunucu tarafı dilinde yapmanın yolunu bulmanız yeterli.
user158017

Apaçi örneği. Şişe örneği.
Bob Stein

Ne yazık ki iOS, içerik düzenlemesi 'ek' olsa bile pdf dosyalarını önizleyecek ve indirmeyecektir.
Jorn van de Beek

14

Gönderilen http başlıklarını değiştirmeniz gerekiyor. Sunucunuza bağlı olarak, .htaccess'inizi aşağıdaki gibi değiştirebilirsiniz:

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

İçerik türü hakkında yalan söylemeye gerek yok. İçerik-eğilimini ayarlamak yeterlidir.
Quentin

9

bir PHP betiği (veya bunun için başka bir sunucu tarafı dili) kullanmanız gerekecek

<?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');
?>

ve pdf yerine PHP dosyasına yeniden yönlendirmek (yeniden yazmak) içinhttacces kullanın


Hmm, php dosyasını doğrudan açtığımda harika çalışıyor. Ancak, burada olduğu gibi yeniden yönlendirmeyi kullanmaya çalıştığımda: 301 /_PDFs/Catalogue.pdf http://www.example.com/_PDFs/___download_the_catalogue_instead_opening.phpdosyasını yeniden yönlendirip pdf dosyasını açmaya çalıştığımda, orijinali tarayıcıda açmaya devam ediyor, bunun yerine yeniden adlandırılmış sürümü
indiriyor

GÜNCELLEME: Doğrudan çağrılan bir dosya yokken çalışır (örneğimde "Catalogue.pdf" olarak). Sonra yeniden yönlendirme mükemmel bir şekilde çalışır. Teşekkürler!
ellockie

8

Kullanabilirsiniz

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

Bu örneğe bakın:

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

Bu ASP.NET için geçerlidir. Diğer tüm sunucu tarafı dillerinde benzer çözümler bulabileceğinize eminim. Ancak bildiğim kadarıyla javascript çözümü yok.


cevap budur (hem de PHP için ilgili olanı). önemli olan, http yanıt başlığının düzenlenmesi gerektiğidir.
user158017

5

Html5 özniteliği olmadan bunu php kullanarak başarabilirsiniz:

Bu kodla download.php adlı php dosyası oluşturun :

<?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();
}

Şimdi otomatik olarak pdf indirmeye başlamak istiyorsanız bu javascript'i yazın:

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

Bunun bir bağlantı üzerinde çalışmasını istiyorsanız, bunu kullanın ...

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

4
Bunu URL parametreleriyle yapacağınız zaman dikkatli olmanız gerektiğine dair bir uyarı. Örneğin $file = $_GET['$file'];. Çünkü o zaman kişi o zaman download.php?file=../../../wp-config.phpveya verilen başka bir kaynağı da arayabilir . Uzantıların, mime türlerinin ve indirilmesine izin verilen yolların ek denetimi (ve "../" gibi şeylerin çıkarılması) çok önemlidir!
Giel Berkers

Ben miyim yoksa <a href='javascript...'> yapmak bağlantıyı doğrudan eklemekle tamamen aynı<a href='download.php'> ?
allan.simon

5

Herhangi bir görüntüyü veya pdf dosyasını yeni sekmede açmak yerine tarayıcıdan doğrudan indirmek istediğinizde, javascript'te dinamik bağlantı oluştur özelliğinin indirme özelliğini ayarlamalısınız.

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

Yeni Chrome güncellemesi için bir süre olay çalışmıyor. bunun için aşağıdaki kod kullanılacaktır

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

Alt öğe eklemek ve çocuğu kaldırmak yalnızca Internet Explorer tarayıcısı olan Firefox için kullanışlıdır. Chrome'da, alt öğe eklemeden ve kaldırmadan çalışır


2

Benim için en çok işe yarayan çözüm, Nick'in blogunda yazdığı çözümdü

Çözümünün temel fikri, Apache sunucuları başlık modunu kullanmak ve .htaccess'i, tüm * .pdf dosyalarını bir ek yerine akış olarak davranmaya zorlayan bir FileMatch yönergesi içerecek şekilde düzenlemektir. Bu aslında HTML'yi düzenlemeyi içermese de (orijinal soruya göre) kendi başına herhangi bir programlama gerektirmez.

Nick'in yaklaşımını tercih etmemin ilk nedeni, onu klasör bazında ayarlamama izin vermesiydi, böylece bir klasördeki PDF'ler tarayıcıda açılabilirken diğerlerine de izin verebilir (kullanıcıların düzenlemesini ve sonra yeniden yüklemesini istediğimiz olanlar) indirme olarak zorlanacak.

Ayrıca, PDF'lerin doldurulabilir formları bir API aracılığıyla sunucularınıza gönderme / gönderme seçeneği olduğunu, ancak bunun uygulanması biraz zaman aldığını da eklemek isterim.

İkinci neden, zamanın bir değerlendirme olmasıdır. Header () içindeki içerik kullanımını zorlamak için bir PHP dosya işleyicisi yazmak da API'den daha kısa, ancak yine de Nick'in yaklaşımından daha uzun sürecektir.

Bir Apache modunu nasıl açacağınızı ve .htaccs'leri nasıl düzenleyeceğinizi biliyorsanız, bunu yaklaşık 10 dakika içinde alabilirsiniz. Linux barındırma gerektirir (Windows değil). Bu, yapılandırmak için yüksek düzeyde sunucu erişimi gerektirdiğinden tüm kullanımlar için uygun bir yaklaşım olmayabilir. Bu nedenle, erişim dediyseniz, bunun nedeni muhtemelen bu iki şeyi nasıl yapacağınızı zaten bilmenizdir. Değilse, daha fazla talimat için Nick'in bloguna bakın.


2

Html5 yolu (önceki cevabım) tüm tarayıcılarda mevcut olmadığından, bu biraz daha hackleme yöntemidir.

Bu çözüm, amaçlanan dosyayı aynı etki alanından sunmanızı gerektirir VEYA CORS iznine sahiptir.

  1. Öncelikle dosyanın içeriğini XMLHttpRequest (Ajax) aracılığıyla indirin.
  2. Ardından, dosyanın içeriğini base64 kodlayarak bir veri URI'si oluşturun ve medya türünü olarak ayarlayın application/octet-stream. Sonuç şöyle görünmeli

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

Şimdi ayarlayın location.href = data. Bu, tarayıcının dosyayı indirmesine neden olacaktır. Maalesef bu şekilde dosya adını veya uzantısını ayarlayamazsınız. Medya türüyle uğraşmak bir şeyler getirebilir.

Ayrıntılara bakın: https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs



1

HTML5 kullanıyorsanız (ve sanırım şimdi herkes bunu kullanıyor), adında bir özellik var download.

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

burada filenameisteğe bağlıdır, ancak sağlanırsa, indirilen dosya için bu adı alır.


Ne yazık ki, bu etiketi anlayamayacak kadar aptal olduğumu itiraf etmeliyim. Bunu <a href="download/Curriculum_it.pdf.zip">Download curriculum</a>ya da şunu söylüyorum <a href="download/Curriculum_it.pdf.zip" download="Curriculum_it">Download curriculum</a>ve nasıl çalıştığı konusunda kesinlikle hiçbir fark göremiyorum. Her ikisi de .zip'imi indiriyor. Ve ikincisinde dosya adı seçeneğini kullanmak hiçbir şey yapmıyor gibi görünüyor.
Garavani

0

Davranış, tarayıcının çeşitli MIME türlerini işleyecek şekilde nasıl ayarlandığına bağlı olmalıdır. Bu durumda MIME türü application / pdf'dir. Tarayıcıyı dosyayı indirmeye zorlamak istiyorsanız, PDF dosyalarında farklı bir MIME türünü zorlamayı deneyebilirsiniz. Buna karşı tavsiye ederim, çünkü kullanıcıların bir PDF dosyasını açtıklarında ne olacağını seçmeleri gerekir.



-1

Sonunda buldum ...... dinamik bağlantı etiketi oluşturun ve üzerine tıklayın

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

"Payment.pdf" yalnızca özel ad içindir.


Bağlantıyı dinamik olarak oluşturmaya gerek yoktur.
Quentin

İndirme özniteliğinin yalnızca aynı kaynaklı istekler için desteklendiğini unutmayın.
Quentin

Bu aynı cevabı gibi görünüyor bu bir üç yıl önceki.
Quentin
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.