Принудительное скачивание PDF с сервера: Content-disposition

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для того, чтобы инициировать загрузку файла на жесткий диск пользователя, используйте HTTP-заголовок Content-Disposition: attachment. Обычно настройка производится на сервере посредством кода или конфигурации. В быстрой программе на PHP это выглядит следующим образом:

php
Скопировать код
header('Content-Disposition: attachment; filename="releaseTheKraken.txt"');

Имя файла "releaseTheKraken.txt" – это пример, можно заменить на любое другое, и этот код заставит браузер пользователя начать загрузку файла на его локальный диск.

Кинга Идем в IT: пошаговый план для смены профессии

Подробнее о загрузке файлов

HTML5 к вашим услугам

Для инициирования загрузки файла на стороне клиента можно использовать атрибут download HTML5 в теге <a>:

HTML
Скопировать код
<a href="/path/to/theKraken" download="UnleashedKraken.pdf">Скачать Кракена</a>

Браузер выполнит указание и сохранит файл с заданным именем и расширением.

Альтернатива для старых браузеров

Если требуется поддержка старых браузеров, таких как MSIE11, не поддерживающих атрибут download, можно создать объект Blob и запустить загрузку вручную:

JS
Скопировать код
function downloadKrakenIE(dataUri, filename) {
  var blob = new Blob([dataUri]);
  window.navigator.msSaveOrOpenBlob(blob, filename);
}

// Пример использования:
downloadKrakenIE(oldSchoolDataUri, 'theKraken');

Универсальный способ загрузки файлов

Из-за различий в поддержке браузеров, стоит объединить все методы в одну функцию, обеспечивающую совместимость:

JS
Скопировать код
function downloadKraken(dataUri, filename) {
  if (window.navigator.msSaveOrOpenBlob) { // Для IE11 и Edge
    downloadKrakenIE(dataUri, filename);
  } else {
    // Для браузеров нового поколения
    var link = document.createElement("a");
    link.href = dataUri;
    link.download = filename;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  }
}

// Готовы к приключениям?
var dataUri = 'data:text/plain;charset=utf-8,Release%20the%20Kraken!';
downloadKraken(dataUri, 'theKraken.txt');

Обработка ошибок при загрузке

Не забывайте обрабатывать исключения при загрузке, чтобы пользователь был в курсе возможных проблем:

JS
Скопировать код
try {
  releaseTheKraken(); // Ваша функция загрузки
} catch(e) {
  alert('Внимание: Кракен не может быть освобожден: ' + e.message);
}

Визуализация

Для наглядности можно представить заголовок Content-disposition как указатели:

Markdown
Скопировать код
Запрос браузера: "Мне нужен этот файл."
Ответ сервера с Content-disposition: "Пожалуйста, сохраните на жесткий диск!"
Без "Content-disposition":
Файл ➡️ 🌐 (открывается в браузере)

С "Content-disposition":
Файл ➡️ 💾 (предлагается к сохранению)

Ключевая мысль: Content-disposition означает "путь к папке с загрузками":

Markdown
Скопировать код
Content-disposition: attachment; filename="guide.pdf" 📄➡️💾
// Без обходных путей. Мы направляемся прямо на ваш жесткий диск.

Избегайте ловушек при загрузке

Кодирование специальных символов

При указании имени файла в заголовке Content-Disposition важно корректно кодировать спецсимволы, чтобы избежать проблем. Используйте rawurlencode в PHP или encodeURIComponent в JavaScript для этого:

php
Скопировать код
header('Content-Disposition: attachment; filename="' . rawurlencode($filename) . '"');

Перезапись заголовков — дело тонкое

Маневрируя с Content-Disposition, обратите внимание, чтобы не перезаписать существующие заголовки. При приоритете последней установки знание особенностей работы с заголовками в выбранном языке или фреймворке оказывается крайне важным.

Рекомендации для гармоничной работы с браузерами

При принудительном запуске загрузки обязательно корректно устанавливайте заголовок Content-Type, соответствующий типу файла:

php
Скопировать код
header('Content-Type: application/pdf');

Полезные материалы

  1. Content-Disposition – HTTP | MDN
  2. RFC 6266 – Использование поля заголовка Content-Disposition
  3. Как закодировать параметр имени файла в заголовке Content-Disposition – Stack Overflow
  4. Атрибут download в HTML – W3Schools
  5. HTTP/1.1: Приложения
  6. GitHub – pillarjs/send: Поддержка статического файлового сервера