Content-Disposition
Применение
В обычном HTTP-ответе заголовок Content-Disposition управляет тем, как браузер показывает содержимое пользователю. Значение inline указывает браузеру отрисовать содержимое напрямую. Значение attachment вместо этого вызывает диалог скачивания.
Этот заголовок также играет роль в ответах multipart/form-data и при отправке форм. Каждая часть multipart-тела включает собственное поле Content-Disposition, определяющее имя поля формы и необязательное имя файла для загружаемых файлов. Граница между частями задаётся в заголовке Content-Type.
inline
Директива inline предписывает браузеру отображать содержимое непосредственно внутри страницы. Это поведение по умолчанию для большинства ответов, когда Content-Disposition отсутствует.
attachment
Директива attachment вызывает запрос на скачивание. Браузер показывает диалог «Сохранить как» вместо отрисовки содержимого в области просмотра.
filename
Параметр filename предлагает имя файла по умолчанию для скачиваемого файла. Значение заключается в двойные кавычки и подчиняется правилам кодировки ASCII.
Content-Disposition: attachment; filename="report.pdf"
filename*
Параметр filename* расширяет filename поддержкой кодировок символов за пределами ASCII. Когда присутствуют и filename, и filename*, приоритет имеет filename*. Это полезно для имён файлов, содержащих символы вне ASCII.
Content-Disposition: attachment; filename="document.pdf"; filename*=UTF-8''d%C3%B6cument.pdf
form-data
Директива form-data встречается в частях multipart-тела и обозначает, что содержимое относится к отправке формы.
name
Параметр name обязателен внутри частей multipart-тела и определяет поле формы, которому соответствует данная часть.
Пример
Сервер, отдающий CSV-файл на скачивание, устанавливает attachment и предлагает имя файла. Браузер открывает диалог сохранения с предзаполненным «export.csv».
Content-Disposition: attachment; filename="export.csv"
Сервер, отображающий PDF прямо в браузере, использует inline. Браузер отрисовывает PDF во встроенном просмотрщике, а не скачивает файл.
Content-Disposition: inline
При отправке multipart-формы каждая часть несёт собственное поле Content-Disposition. Параметр name сопоставляет часть с соответствующим полем формы, а filename указывает исходное имя загруженного файла.
Content-Disposition: form-data; name="avatar"; filename="photo.jpg"
Диагностика
Проблемы со скачиванием и отображением, связанные с Content-Disposition, обычно вызваны неверными значениями директив или ошибками в кодировании имени файла.
Файл скачивается с неправильным именем. Браузер использует параметр filename как имя сохранения по умолчанию. Отсутствующее или некорректно сформированное значение filename заставляет браузер откатиться к пути URL или к универсальному имени. Убедитесь, что значение заключено в двойные кавычки: filename=“report.pdf”. Проверьте заголовок командой curl -I https://example.re/file и посмотрите параметр filename в ответе.
Символы вне ASCII в именах файлов ломаются или отображаются как мусор. Параметр filename поддерживает только ASCII-символы. Для имён с диакритическими знаками, символами CJK или другим текстом вне ASCII добавьте параметр filename*, используя синтаксис кодирования: filename*=UTF-8”d%C3%B6cument.pdf. Указывайте оба параметра — filename (ASCII-запасной вариант) и filename* (кодированная версия) — для максимальной совместимости с браузерами.
Браузер игнорирует attachment и показывает содержимое встроенно. Некоторые браузеры переопределяют attachment для типов содержимого, которые отрисовывают нативно, например PDF и изображения. На это поведение влияет заголовок Content-Type. Установка Content-Type: application/octet-stream вместе с attachment принудительно запускает скачивание для файла любого типа. Расширения браузера и встроенные просмотрщики (PDF.js) также могут переопределить директиву.
Встроенное отображение срабатывает там, где ожидается скачивание. При отсутствии заголовка Content-Disposition для большинства типов содержимого по умолчанию применяется inline. Чтобы вызвать скачивание, сервер должен явно отправить attachment. В nginx добавьте add_header Content-Disposition “attachment”; в соответствующий блок location. В Apache используйте Header set Content-Disposition “attachment” внутри директивы
Приоритет filename и filename*. Когда присутствуют оба параметра, во всех современных браузерах приоритет имеет filename*. Старые клиенты, не поддерживающие filename*, откатываются к filename. Всегда указывайте оба параметра. Значение filename* должно использовать процентное кодирование для специальных символов: filename*=UTF-8”na%C3%AFve.txt.
Вспомогательные методы фреймворков для ответов со скачиванием. Большинство веб-фреймворков предоставляют встроенные методы для установки заголовков скачивания. Django использует FileResponse с параметром as_attachment. Express использует res.download(). Flask использует send_file() с as_attachment=True. Rails использует send_data или send_file с опцией disposition. Эти методы сами обрабатывают кодирование имени файла и формирование заголовка, снижая вероятность ручных ошибок.