(HTML) Загрузите файл PDF вместо того, чтобы открывать его в браузере при нажатии


115

Мне было интересно, как сделать ссылку на файл PDF загружаемой вместо того, чтобы открывать их в браузере? Как это сделать в html? (Я бы предположил, что это сделано через javascript или что-то в этом роде).


3
Насколько мне известно, это поведение не зависит от сценария. Большинство браузеров имеют свои собственные настройки поведения для определенных типов файлов при загрузке.
Барт

1
Начиная с HTML5, OP должен обновить правильный ответ на ответ Сарима.
Омар Тарик


На этот вопрос также был дан ответ здесь: stackoverflow.com/a/30714824/847235
intrepidis

Ответы:


39

Вы не можете сделать это с помощью HTML. Это серверное решение. Вы должны передать файл в потоковом режиме, чтобы браузер запускал диалог сохранения.

Я бы посоветовал этого не делать. Как пользователь взаимодействует с PDF-файлом, следует оставить на усмотрение пользователя.

ОБНОВЛЕНИЕ (2014 г.):

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

Я согласен и считаю, что ответ Сарима хорош (вероятно, это должен быть выбранный ответ, если OP когда-либо вернется). Однако этот ответ по-прежнему является надежным способом справиться с этим (как указывает ответ Йигита Йенера, и, как ни странно, люди согласны с этим). Хотя атрибут загрузки получил поддержку, он все еще нестабилен:

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


9
Я согласен, что при других обстоятельствах лучше оставить это на усмотрение пользователя. Однако я пришел в эту ветку в поисках ответа, и отмеченный «ответ» не был ответом - это было «вы не должны этого делать». Для меня это не ответ на вопрос. Вместо этого дайте конкретный ответ, а также совет.
user158017

1
Иногда вопрос неправильный. ;) В любом случае, что касается вашей проблемы, это все проблема UX. Иногда необходимо заставить Интернет вести себя определенным образом, но часто есть лучшие решения с точки зрения UX. Кроме того, мой ответ правильный. Вы не можете делать то, что хотите, с HTML (вот о чем был задан вопрос). Это как серверное решение.
Д.А.

1
Это один из моих самых странных ответов. Люди все еще находят способ проголосовать против него. Что нормально! Но было бы интересно узнать почему.
Д.А.

3
Что касается этого отрицательного голосования, это может быть крахом цивилизации, насколько легко натолкнуться на непреднамеренно высокомерный текст. Этот ответ поражает меня своим покровительственным мнением и недостатком ответов. Вместо пункта 1 просто добавьте httpтег к вопросу. Вместо абзаца 2: «Возможно, вы захотите пересмотреть, отвечает ли предотвращение немедленного просмотра PDF-файлов в интересах всех пользователей. Сказав это ...» Затем предположите, что OP и будущие читатели уже взрослые, и переходите к действенному ответу, например Йенеру .
Боб Стейн,

1
@ BobStein-VisiBone Полностью согласен!
Д.А.

132

Теперь это возможно с html5. Установите атрибут "загрузка" в элементе.

<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 из div html, но я не хочу открывать другое окно, загрузка должна быть такой же
бесполезной,

1
На данный момент в августе 2019 года поддержка браузера, похоже, улучшена для этой функции, см .: w3schools.com/tags/att_a_download.asp
Дэниел Реш,

2
Обратите внимание, что атрибут загрузки поддерживается только для запросов с одним и тем же источником.
Квентин

83

Это возможно только при установке заголовка HTTP-ответа кодом на стороне сервера. А именно,

Content-Disposition: attachment; filename=fname.ext

2
это идеальный ответ - просто найдите способ сделать это на соответствующем серверном языке.
user158017

Пример Apache . Пример фляги .
Боб Стейн,

К сожалению, iOS по-прежнему будет выполнять предварительный просмотр и не загружать файлы PDF, даже если расположение содержимого - «вложение».
Йорн ван де Бик

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 напрямую. Но когда я пытаюсь использовать перенаправление, как здесь: Redirect 301 /_PDFs/Catalogue.pdf http://www.example.com/_PDFs/___download_the_catalogue_instead_opening.phpи пытаюсь открыть файл pdf, он все равно открывает оригинал в браузере, вместо этого загружая переименованную версию ...
Эллоки,

ОБНОВЛЕНИЕ: работает, когда нет файла, который вызывается напрямую (в моем примере это «Catalogue.pdf»). Тогда перенаправление работает отлично. Спасибо!
ellockie

8

Ты можешь использовать

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

Посмотрите этот пример:

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

Это касается ASP.NET. Я уверен, что вы можете найти аналогичные решения на всех других серверных языках. Однако, насколько мне известно, решения javascript не существует.


это ответ (а также связанный с ним для 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или любой другой данный ресурс. Дополнительная проверка расширений, MIME-типов и разрешенных путей для загрузки (и удаление таких вещей, как "../") очень важна!
Гиль Беркерс

это я или выполнение <a href='javascript...'> точно такое же, как прямое <a href='download.php'> ?
добавление

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 для принудительного размещения содержимого в header () также займет меньше времени, чем 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+ sure+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.


Это лучшее решение javascript для загрузок в другом домене.
Эдхоулер,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.