(HTML) ดาวน์โหลดไฟล์ PDF แทนที่จะเปิดในเบราว์เซอร์เมื่อคลิก


115

ฉันสงสัยว่าจะดาวน์โหลดลิงก์ไฟล์ PDF ได้อย่างไรแทนที่จะเปิดในเบราว์เซอร์ สิ่งนี้ทำได้อย่างไรใน html (ฉันคิดว่ามันทำผ่านจาวาสคริปต์หรืออะไรสักอย่าง)


3
นี่คือความรู้ของฉันพฤติกรรมที่ไม่สามารถเขียนสคริปต์ได้ เบราว์เซอร์ส่วนใหญ่จะมีการตั้งค่าของตัวเองสำหรับลักษณะการทำงานของสิ่งที่ต้องทำกับไฟล์บางประเภทเมื่อดาวน์โหลด
บาร์ต

1
สำหรับ HTML5 OP ควรอัปเดตคำตอบที่ถูกต้องสำหรับคำตอบของ Sarim
Omar Tariq


คำถามนี้มีคำตอบที่นี่เช่นกัน: stackoverflow.com/a/30714824/847235
intrepidis

คำตอบ:


39

คุณไม่สามารถทำได้ด้วย HTML เป็นโซลูชันบนเซิร์ฟเวอร์ คุณต้องสตรีมไฟล์เพื่อให้เบราว์เซอร์เรียกใช้กล่องโต้ตอบบันทึก

ฉันไม่แนะนำให้ทำเช่นนี้ วิธีที่ผู้ใช้โต้ตอบกับ PDF ควรปล่อยไว้ให้ผู้ใช้

อัพเดท (2014):

ดังนั้น ... คำตอบนี้ยังคงได้รับการโหวตต่ำมากมาย ฉันคิดว่าส่วนหนึ่งคือคำตอบนี้เมื่อ 4 ปีก่อนและดังที่ Sarim ชี้ให้เห็นตอนนี้มีแอตทริบิวต์HTML 5downloadที่สามารถจัดการสิ่งนี้ได้

ฉันเห็นด้วยและคิดว่าคำตอบของ Sarim นั้นดี (อาจเป็นคำตอบที่เลือกหาก OP กลับมา) อย่างไรก็ตามคำตอบนี้ยังคงเป็นวิธีที่เชื่อถือได้ในการจัดการ (ดังที่คำตอบของYiğit Yener ชี้ให้เห็นและ - แปลก - ผู้คนเห็นด้วย) แม้ว่าแอตทริบิวต์การดาวน์โหลดจะได้รับการสนับสนุน แต่ก็ยังไม่แน่นอน:

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


9
ฉันยอมรับว่าภายใต้สถานการณ์อื่นปล่อยให้ผู้ใช้ควบคุมจะดีกว่า อย่างไรก็ตามฉันมาที่ชุดข้อความนี้เพื่อหาคำตอบและ "คำตอบ" ที่เลือกไว้ไม่ใช่คำตอบ แต่เป็น "คุณไม่ควรทำอย่างนั้น" สำหรับฉันแล้วนั่นไม่ใช่คำตอบสำหรับคำถาม แต่ให้ คำตอบที่เฉพาะเจาะจงและให้คำแนะนำด้วย
user158017

1
บางครั้งคำถามผิด ;) อย่างไรก็ตามเกี่ยวกับปัญหาของคุณนั่นคือปัญหา UX ทั้งหมด การบังคับให้เว็บทำงานในรูปแบบเฉพาะบางครั้งก็จำเป็น แต่มักจะมีวิธีแก้ปัญหาที่ดีกว่าจากมุมมองของ UX นอกจากนี้คำตอบของฉันถูกต้อง คุณไม่สามารถทำสิ่งที่คุณต้องการทำกับ HTML ได้ (ซึ่งเป็นสิ่งที่ถาม) เป็นโซลูชันฝั่งเซิร์ฟเวอร์
DA.

1
นี่เป็นหนึ่งในคำตอบที่แปลกประหลาดที่สุดที่ฉันเคยโพสต์ ผู้คนยังคงหาทางที่นี่เพื่อลดคะแนน ไม่เป็นไร! แต่มันน่าสนใจที่จะรู้ว่าทำไม
DA.

3
เกี่ยวกับการลงคะแนนนั้นอาจเป็นความหายนะของอารยธรรมที่ง่ายแค่ไหนที่จะเจอข้อความหยิ่งยโสโดยไม่ได้ตั้งใจ คำตอบนี้ทำให้ฉันประทับใจตราบเท่าที่มีความคิดเห็นและคำตอบสั้น ๆ แทนวรรค 1 เพียงเพิ่มhttpแท็กให้กับคำถาม แทนที่จะเป็นย่อหน้าที่ 2: "คุณอาจต้องการพิจารณาใหม่ว่าการป้องกันการดู PDF ในทันทีนั้นเป็นประโยชน์สูงสุดของผู้ใช้ทุกคนหรือไม่กล่าวว่า ... " จากนั้นถือว่า OP และผู้อ่านในอนาคตเป็นผู้ใหญ่และไปยังคำตอบที่สามารถดำเนินการได้เช่นYener's .
Bob Stein

1
@ BobStein-VisiBone ฉันเห็นด้วยทั้งหมด!
DA.

132

ด้วย html5 ตอนนี้เป็นไปได้แล้ว ตั้งค่า Attr "ดาวน์โหลด" ในองค์ประกอบ

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

ที่มา: http://updates.html5rocks.com/2011/08/Downloading-resources-in-HTML5-a-download


คุณควรใช้โซลูชันนี้หากได้รับการสนับสนุน นี่คือวิธีตรวจสอบว่าเป็นif ("download" in document.createElement("a")){ ... }
pmrotule

ฉันเพิ่มคำตอบอื่นด้านล่าง (แม้ว่าแฮ็คที่ไม่ดี) ในขณะที่นี่ยังคงเป็นวิธีที่ต้องการ แต่อาจมีการนำเสนอวิธีแฮ็กสำหรับเบราว์เซอร์ที่ไม่รองรับ
Sarim

มีวิธีหนึ่งที่สามารถระบุข้อความสำหรับ pdf แทนการกล่าวถึงเส้นทางไฟล์ได้หรือไม่? ฉันต้องการสร้าง pdf จาก html div แต่ฉันไม่ต้องการเปิดหน้าต่างอื่นการดาวน์โหลดน่าจะดูเหมือนในคำตอบนี้ ..
T.Adak

1
ณ ตอนนี้ในเดือนสิงหาคม 2019 การรองรับเบราว์เซอร์ดูเหมือนจะได้รับการปรับปรุงสำหรับคุณลักษณะนี้โปรดดู: w3schools.com/tags/att_a_download.asp
Daniel Resch

2
โปรดทราบว่าแอตทริบิวต์การดาวน์โหลดได้รับการสนับสนุนสำหรับคำขอที่มาเดียวกันเท่านั้น
Quentin

83

สิ่งนี้ทำได้เฉพาะกับการตั้งค่าส่วนหัวการตอบกลับ http โดยรหัสฝั่งเซิร์ฟเวอร์ ได้แก่ ;

Content-Disposition: attachment; filename=fname.ext

2
นี่คือคำตอบที่สมบูรณ์แบบ - เพียงแค่หาวิธีดำเนินการในภาษาฝั่งเซิร์ฟเวอร์ที่เหมาะสม
user158017

ตัวอย่างApache ตัวอย่างขวด
Bob Stein

น่าเสียดายที่ iOS ยังคงดูตัวอย่างและไม่ดาวน์โหลดไฟล์ pdf แม้ว่าการจัดการเนื้อหาจะเป็น "ไฟล์แนบ" ก็ตาม
Jorn van de Beek

9

คุณจะต้องใช้สคริปต์ PHP (หรือภาษาฝั่งเซิร์ฟเวอร์อื่นสำหรับสิ่งนี้)

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

และใช้ HTTacces เพื่อเปลี่ยนเส้นทาง (เขียนใหม่) ไปยังไฟล์ PHP แทน pdf


อืมมันใช้งานได้ดีเมื่อฉันเปิดไฟล์ php โดยตรง แต่เมื่อฉันพยายามใช้การเปลี่ยนเส้นทางเช่นที่นี่: เปลี่ยนเส้นทาง 301 /_PDFs/Catalogue.pdf http://www.example.com/_PDFs/___download_the_catalogue_instead_opening.phpแล้วลองเปิดไฟล์ pdf มันก็ยังเปิดไฟล์ต้นฉบับในเบราว์เซอร์แทนดาวน์โหลดเวอร์ชันที่เปลี่ยนชื่อ ...
ellockie

อัปเดต: ใช้งานได้เมื่อไม่มีไฟล์ที่ถูกเรียกโดยตรง (เป็น "Catalogue.pdf" ในตัวอย่างของฉัน) จากนั้นการเปลี่ยนเส้นทางจะทำงานได้อย่างสมบูรณ์ ขอบคุณ!
ellockie

8

คุณสามารถใช้ได้

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

ดูตัวอย่างนี้:

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

สิ่งนี้ใช้สำหรับ ASP.NET ฉันแน่ใจว่าคุณสามารถค้นหาโซลูชันที่คล้ายกันในภาษาฝั่งเซิร์ฟเวอร์อื่น ๆ ทั้งหมด อย่างไรก็ตามไม่มีวิธีแก้ปัญหาจาวาสคริปต์ที่ดีที่สุดเท่าที่ฉันรู้


นี่คือคำตอบ (เช่นเดียวกับคำตอบที่เกี่ยวข้องสำหรับ PHP) ประเด็นคือต้องแก้ไขส่วนหัวการตอบกลับ http
user158017

5

หากไม่มีแอตทริบิวต์ html5 ก็สามารถทำได้โดยใช้ php:

สร้างไฟล์ php ชื่อdownload.phpด้วยรหัสนี้:

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

ตอนนี้หากคุณต้องการเริ่มดาวน์โหลด pdf โดยอัตโนมัติให้เขียน javascript นี้:

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

หากคุณต้องการให้สิ่งนี้ทำงานบนลิงก์ให้ใช้สิ่งนี้ ...

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

4
โปรดทราบว่าคุณต้องระมัดระวังเมื่อคุณจะทำสิ่งนี้กับพารามิเตอร์ URL ตัวอย่างเช่น$file = $_GET['$file'];. เนื่องจากสามารถโทรdownload.php?file=../../../wp-config.phpหรือทรัพยากรอื่น ๆ ได้ การตรวจสอบส่วนขยายประเภทละครใบ้และเส้นทางที่อนุญาตให้ดาวน์โหลดเพิ่มเติมจาก (และการลอกสิ่งต่างๆเช่น "../") มีความสำคัญมาก!
Giel Berkers

เป็นฉันเองหรือทำ <a href='javascript ...'> เหมือนกับการใส่ลิงก์โดยตรง<a href='download.php'> ?
allan.simon

5

เมื่อคุณต้องการดาวน์โหลดรูปภาพหรือไฟล์ pdf โดยตรงจากเบราว์เซอร์แทนที่จะเปิดในแท็บใหม่จากนั้นในจาวาสคริปต์คุณควรตั้งค่าเพื่อดาวน์โหลดแอตทริบิวต์ของการสร้างลิงก์แบบไดนามิก

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

สำหรับการอัปเดต Chrome ใหม่บางครั้งเหตุการณ์ไม่ทำงาน สำหรับรหัสต่อไปนี้จะถูกใช้

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

การต่อท้ายเด็กและการนำเด็กออกมีประโยชน์สำหรับเบราว์เซอร์ Firefox, Internet explorer เท่านั้น บน Chrome จะทำงานได้โดยไม่ต้องต่อท้ายและนำเด็กออก


2

วิธีแก้ปัญหาที่ได้ผลดีที่สุดสำหรับฉันคือสิ่งที่Nickเขียนขึ้นในบล็อกของเขา

แนวคิดพื้นฐานในการแก้ปัญหาของเขาคือการใช้ตัวดัดแปลงส่วนหัวของเซิร์ฟเวอร์ Apache และแก้ไข. htaccess เพื่อรวมคำสั่ง FileMatch ที่บังคับให้ไฟล์ * .pdf ทั้งหมดทำหน้าที่เป็นสตรีมแทนที่จะเป็นไฟล์แนบ แม้ว่าสิ่งนี้จะไม่เกี่ยวข้องกับการแก้ไข HTML (ตามคำถามเดิม) แต่ก็ไม่จำเป็นต้องมีการเขียนโปรแกรมใด ๆ

เหตุผลแรกที่ฉันชอบแนวทางของ Nick เพราะอนุญาตให้ฉันตั้งค่าเป็นรายโฟลเดอร์ดังนั้น PDF ในโฟลเดอร์เดียวจึงยังสามารถเปิดได้ในเบราว์เซอร์ในขณะที่อนุญาตให้ผู้อื่น (สิ่งที่เราต้องการให้ผู้ใช้แก้ไขแล้วอัปโหลดใหม่) ถูกบังคับให้ดาวน์โหลด

ฉันต้องการเพิ่มว่ามีตัวเลือก PDF ในการโพสต์ / ส่งแบบฟอร์มที่กรอกได้ผ่าน API ไปยังเซิร์ฟเวอร์ของคุณ แต่ต้องใช้เวลาสักครู่ในการใช้งาน

เหตุผลที่สองเป็นเพราะเวลาเป็นสิ่งที่ต้องคำนึงถึง การเขียนตัวจัดการไฟล์ PHP เพื่อบังคับให้มีการจัดการเนื้อหาในส่วนหัว () จะใช้เวลาน้อยกว่า API แต่ก็ยังนานกว่าวิธีการของ Nick

ถ้าคุณรู้วิธีเปิด Apache mod และแก้ไข. htaccss คุณจะทำได้ในเวลาประมาณ 10 นาที ต้องใช้โฮสติ้ง Linux (ไม่ใช่ Windows) นี่อาจไม่ใช่แนวทางที่เหมาะสมสำหรับการใช้งานทั้งหมดเนื่องจากต้องมีการเข้าถึงเซิร์ฟเวอร์ระดับสูงเพื่อกำหนดค่า ดังนั้นหากคุณบอกว่าการเข้าถึงอาจเป็นเพราะคุณรู้วิธีทำสองสิ่งนั้นแล้ว ถ้าไม่มีให้ตรวจสอบบล็อกของ Nick สำหรับคำแนะนำเพิ่มเติม


2

เนื่องจากวิธี html5 (คำตอบก่อนหน้าของฉัน) ไม่สามารถใช้ได้ในทุกเบราว์เซอร์จึงมีวิธีแฮ็คเล็กน้อย

โซลูชันนี้ต้องการให้คุณใช้งานไฟล์ที่ต้องการจากโดเมนเดียวกันหรือได้รับอนุญาตจาก CORS

  1. ก่อนอื่นให้ดาวน์โหลดเนื้อหาของไฟล์ผ่าน XMLHttpRequest (Ajax)
  2. จากนั้นให้ข้อมูล URI โดย base64 application/octet-streamเข้ารหัสเนื้อหาของไฟล์และการตั้งค่าสื่อชนิด ผลลัพธ์ควรมีลักษณะดังนี้

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

location.href = dataตั้งตอนนี้ ซึ่งจะทำให้เบราว์เซอร์ดาวน์โหลดไฟล์ ขออภัยคุณไม่สามารถตั้งชื่อไฟล์หรือนามสกุลด้วยวิธีนี้ การเล่นซอกับสื่ออาจให้ผลบางอย่าง

ดูรายละเอียด: https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs


1

ฉันต้องทำสิ่งนี้สำหรับไฟล์ที่สร้างด้วยชื่อไดนามิกในโฟลเดอร์เฉพาะและให้บริการโดย IIS

สิ่งนี้ใช้ได้ผลสำหรับฉัน:

  • ใน IIS ไปที่โฟลเดอร์นั้นแล้วดับเบิลคลิก HTTP Response Headers
  • เพิ่มส่วนหัวใหม่ด้วยข้อมูลต่อไปนี้:

    Name: content-disposition Value: attachment

(จาก: http://forums.iis.net/t/1175103.aspx?add+CustomHeaders+only+for+certain+file+types+ )


1

หากคุณกำลังใช้ HTML5 (และผมคิดว่าตอนนี้ใช้วันที่ทุกคน) downloadมีคุณลักษณะที่เรียกว่า

เช่น <a href="somepathto.pdf" download="filename">

นี่filenameเป็นทางเลือก แต่ถ้ามีให้จะใช้ชื่อนี้สำหรับไฟล์ที่ดาวน์โหลด


น่าเศร้าที่ฉันต้องยอมรับว่าฉันโง่เกินไปที่จะเข้าใจแท็กนี้ ฉันใส่สิ่งนี้: <a href="download/Curriculum_it.pdf.zip">Download curriculum</a>หรือนั่น: <a href="download/Curriculum_it.pdf.zip" download="Curriculum_it">Download curriculum</a>และฉันไม่เห็นความแตกต่างอย่างแน่นอนในการทำงาน ทั้งการดาวน์โหลดไฟล์. zip ของฉัน และในอันที่สองโดยใช้ตัวเลือกชื่อไฟล์ดูเหมือนว่าจะไม่ทำอะไรเลย
Garavani

0

ลักษณะการทำงานควรขึ้นอยู่กับวิธีการตั้งค่าเบราว์เซอร์เพื่อจัดการ MIME ประเภทต่างๆ ในกรณีนี้ประเภท MIME คือ application / pdf หากคุณต้องการบังคับให้เบราว์เซอร์ดาวน์โหลดไฟล์คุณสามารถลองบังคับ MIME ประเภทอื่นในไฟล์ PDF ฉันขอแนะนำให้ทำเช่นนี้เนื่องจากควรเป็นทางเลือกของผู้ใช้ว่าจะเกิดอะไรขึ้นเมื่อเปิดไฟล์ PDF


-1

คุณสามารถใช้ download.js ( https://github.com/rndme/downloadและhttp://danml.com/download.html ) หากไฟล์อยู่ใน URL ภายนอกคุณต้องทำการร้องขอ Ajax แต่ถ้าไม่ใช่คุณสามารถใช้ฟังก์ชัน:

download(Path, name, mime)

อ่านเอกสารประกอบสำหรับรายละเอียดเพิ่มเติมใน GitHub


นี่เป็นโซลูชันจาวาสคริปต์ที่ดีที่สุดสำหรับการดาวน์โหลดในโดเมนอื่น
Edhowler
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.