(HTML) Завантажте PDF-файл, а не відкривайте їх у браузері при натисканні


115

Мені було цікаво, як зробити посилання на файл PDF для завантаження, а не відкривати їх у браузері? Як це робиться в html? (Я припускаю, що це робиться через javascript чи щось таке).


3
Це, наскільки мені відомо, не сценарій поведінки. Більшість браузерів матимуть власні налаштування щодо поведінки, що робити з певними типами файлів при завантаженні.
Барт

1
Що стосується HTML5, то ОП має оновити правильну відповідь на відповідь Саріма.
Омар Тарік


На це питання також відповіли тут: stackoverflow.com/a/30714824/847235
intrepidis

Відповіді:


38

Ви не можете зробити це за допомогою HTML. Це серверне рішення. Ви повинні передавати файл так, щоб браузер не запускав діалогове вікно збереження.

Я б радив цього не робити. Як користувач взаємодіє з PDF-файлом, слід залишати його.

ОНОВЛЕННЯ (2014):

Отже ... ця відповідь все ще отримує багато відгуків. Я припускаю, що частина цього полягає в тому, що на це відповіли 4 роки тому, і як зазначає Сарім, зараз існує атрибут HTML 5,download який може це впоратися.

Я згоден, і вважаю, що відповідь Саріма є хорошою (це, мабуть, має бути обрана відповідь, якщо ОП коли-небудь повернеться). Однак ця відповідь все ще є надійним способом її вирішення (як вказує відповідь Ісіта Єнера і - як не дивно - люди згодні). Хоча атрибут завантаження отримав підтримку, він все ще помітний:

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


18
Я знаю, що це рік - але я не згоден. Є обставини, за яких змушувати цю поведінку дуже важливо для потоку додатків. Фактична відповідь полягає у встановленні змісту-диспозиції у заголовку на "вкладення" замість "вбудованого".
користувач158017

9
Я погоджуюся, що за інших обставин краще передати це контролю користувача. Однак я підійшов до цієї теми, шукаючи відповідь, і відмічена "відповідь" не була відповіддю - це було "ти не повинен цього робити". Для мене це не відповідь на питання. Натомість дайте відповідь конкретну відповідь, а також порадити
користувач158017

1
Іноді питання неправильне. ;) У будь-якому випадку, щодо вашої проблеми, це все проблема UX. Іноді змушувати Інтернет вести себе певними способами іноді необхідно, але часто є кращі рішення з точки зору UX. Також моя відповідь правильна. Ви не можете робити те, що хочете зробити з HTML (про що задавали питання). Це як рішення на стороні сервера.
DA.

1
Це одна з найдивовижніших моїх відповідей. Люди як і раніше знаходять свій шлях, щоб спростувати це. Що добре! Але було б цікаво дізнатися, чому.
DA.

3
З цього приводу, що може спричинити падіння цивілізації, наскільки легко навмисно натрапити на текст. Ця відповідь вражає мене як покровительської думки, так і короткої. Замість пункту 1 просто додайте httpтег до питання. Замість пункту 2: "Ви можете переглянути, чи запобігання негайного перегляду PDF-файлів є в інтересах усіх користувачів. Сказавши це ..." Тоді припустімо, що ОП та майбутні читачі є дорослими, і перейдіть до відповіді, що може бути прийнятною, наприклад, як Єнер .
Боб Штейн

133

З 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

Я додав ще одну відповідь нижче (хоча поганий злом), хоча це все ще є кращим способом, можливо, спосіб злому може бути запропонований для непідтримуваних браузерів.
Сарим

Чи є спосіб вказати текст для pdf, а не згадувати шлях до файлу? Мені потрібно створити pdf з HTML html, але я не хочу відкривати інше вікно, завантаження має бути схожим на цю відповідь ..
T.Adak

1
Оскільки зараз у серпні 2019 року підтримка веб-переглядача, як видається, покращується для цієї функції, див: w3schools.com/tags/att_a_download.asp
Daniel Resch

2
Зауважте, що атрибут завантаження підтримується лише для запитів того самого походження.
Квентін

82

Це можливо лише при встановленні заголовка відповіді http кодом сторони сервера. А саме;

Content-Disposition: attachment; filename=fname.ext

2
це ідеальна відповідь - просто знайдіть спосіб зробити це відповідною мовою на стороні сервера.
користувач158017

Приклад Apache . Приклад колби .
Боб Штейн

На жаль, iOS все ще буде попередньо переглядати та не завантажувати файли pdf, навіть якщо вміст є "вкладенням".
Jorn van de Beek

14

Потрібно змінити надіслані заголовки http. Залежно від вашого сервера, ви можете змінити .htaccess таким чином:

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

Не потрібно брехати про тип вмісту. Встановлення вмісту-диспозиції є достатнім.
Квентін

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. Я впевнений, що ви можете знайти подібні рішення на всіх інших мовах сервера. Однак, наскільки я не знаю, немає рішення в JavaScript.


це відповідь (як і відповідна для PHP). справа в тому, що заголовок відповіді http має бути відредагований.
користувач158017

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або будь-який інший ресурс. Додаткова перевірка на наявність розширень, типів mime та дозволених шляхів для завантаження з них (та зачистки матеріалів на зразок "../") дуже важлива!
Giel Berkers

це я чи роблю <a href='javascript...'> точно так само, як безпосередньо посилання в<a href='download.php'> ?
allan.simon

5

Якщо ви хочете безпосередньо завантажити будь-яке зображення або pdf-файл із браузера, замість того, щоб відкрити його в новій вкладці, тоді в javascript слід встановити значення для завантаження атрибуту створення динамічного посилання

    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. На хромі він буде працювати, не додаючи і не знімаючи дитину


2

Найкраще для мене було рішення, яке написав Нік у своєму блозі

Основна ідея його рішення - використовувати мод заголовків серверів Apache та редагувати .htaccess для включення директиви FileMatch, яка змушує всі файли * .pdf діяти як потік замість вкладення. Хоча це насправді не передбачає редагування HTML (відповідно до оригінального запитання), воно не вимагає програмного забезпечення як такого.

Перша причина, яку я віддав перевагу підходу Ніка, це тому, що він дозволив мені встановити його на основі кожної папки, щоб PDF-файли в одній папці все ще могли бути відкриті у браузері, дозволяючи іншим (ті, які ми хотіли б, щоб користувачі редагували та повторно завантажували) бути примусовим як завантаження.

Я також хотів би додати, що існує можливість з PDF-файлами розміщувати / надсилати заповнені форми через API на ваші сервери, але це потребує певного часу.

Друга причина була в тому, що час - це розгляд. Написання обробника файлів PHP для примусового розміщення вмісту у заголовку () також займе менше часу, ніж API, але все ж довше, ніж підхід Ніка.

Якщо ви знаєте, як увімкнути мод Apache та відредагувати .htaccss, ви можете отримати це приблизно за 10 хвилин. Для цього потрібен хостинг Linux (не Windows). Це може бути не підходящим підходом для всіх застосувань, оскільки для налаштування потрібен доступ до сервера високого рівня. Як такий, якщо ви сказали доступ, це, мабуть, тому, що ви вже знаєте, як робити ці дві речі. Якщо ні, перегляньте блог Ніка для отримання додаткових інструкцій.


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.
  • Додайте новий заголовок із такою інформацією:

    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. А у другому з використанням параметра імені файлів, здається, взагалі нічого не робиться.
Гаравані

0

Поведінка повинна залежати від того, як браузер налаштований на обробку різних типів MIME. У цьому випадку тип MIME - це application / pdf. Якщо ви хочете змусити браузер завантажувати файл, ви можете спробувати форсувати інший тип MIME у файлах PDF. Я рекомендую проти цього, оскільки саме користувачі повинні вибрати, що буде, коли вони відкриють файл PDF.


0

Ви можете використовувати download.js ( https://github.com/rndme/download та http://danml.com/download.html ). Якщо файл знаходиться у зовнішній URL-адресі, ви повинні зробити запит Ajax, але якщо його немає, ви можете використовувати функцію:

download(Path, name, mime)

Прочитайте їх документацію для отримання більш детальної інформації в GitHub.


Це найкраще рішення JavaScript для завантаження в інший домен.
Edhowler

-1

Нарешті я знайшов ...... створити динамічний тег якоря та натиснути на нього

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

"Payment.pdf" призначений лише для власної назви.


Немає необхідності динамічно генерувати посилання.
Квентін

Зауважте, що атрибут завантаження підтримується лише для запитів того самого походження.
Квентін

Здається, це така ж відповідь, як і ця, що була проведена трьома роками раніше.
Квентін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.