hx-download
Загружайте файлы с hx-swap='download'
Расширение download сохраняет ответ как загружаемый файл, а не подставляет его в DOM. Оно передаёт тело ответа потоком и генерирует события прогресса.
Оно активируется тремя способами:
-
hx-swap="download"на элементе - Сервер отвечает с
Content-Disposition: attachment(определяется автоматически, атрибут не требуется) - Сервер отвечает с
HX-Download: <url>(расширение загружает этот URL как файл, а исходный ответ при этом подставляется обычным образом)
Установка
<script src="https://cdn.jsdelivr.net/npm/htmx.org@4.0.0/dist/htmx.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/htmx.org@4.0.0/dist/ext/hx-download.js"></script>
Использование
Явный стиль подстановки
Используйте hx-swap="download", чтобы всегда обрабатывать ответ как загружаемый файл:
<button hx-get="/files/report.pdf" hx-swap="download">
Download Report
</button> Автоопределение по Content-Disposition
Если сервер возвращает Content-Disposition: attachment, расширение автоматически запускает загрузку — hx-swap не требуется:
<button hx-get="/files/report.pdf" hx-target="#result">
Download Report
</button> Content-Disposition: attachment; filename="report.pdf"
Заголовок HX-Download
Если серверная часть не может передать файл непосредственно как ответ htmx (например, если нужно перенаправить запрос на отдельную конечную точку загрузки), верните заголовок HX-Download, указывающий на URL файла. Расширение загрузит файл по этому URL, а htmx обработает тело исходного ответа как обычную подстановку:
<button hx-get="/prepare-download" hx-target="#status">
Download Report
</button> HX-Download: /files/report.pdf Content-Type: text/html <span>Your download has started...</span>
<span> подставляется в #status, а файл по адресу /files/report.pdf загружается одновременно.
Этот подход также позволяет избежать проблемы очистки индикаторов и отключённых элементов, возникающей при использовании HX-Redirect со ссылкой на URL загрузки: индикаторы корректно очищаются после завершения исходного запроса.
Индикатор выполнения
По мере поступления ответа расширение генерирует события на исходном элементе:
<button hx-get="/files/report.pdf" hx-swap="download">
Download Report
</button>
<progress id="prog" value="0" max="100"></progress>
<script>
document.body.addEventListener("htmx:download:progress", e => {
document.getElementById("prog").value = e.detail.percent
})
</script> Для отображения прогресса в процентах сервер должен отправлять заголовок Content-Length. Без него percent будет иметь значение null, и будут доступны только loaded (полученные байты).
События
| Событие | Данные | Описание |
|---|---|---|
htmx:download:start |
{total} |
Заголовки ответа получены, начинается передача потоком. total имеет значение null, если отсутствует Content-Length
|
htmx:download:progress |
{loaded, total, percent} |
Генерируется для каждого полученного фрагмента. percent имеет значение null, если отсутствует Content-Length
|
htmx:download:complete |
{filename, size} |
В браузере запущена загрузка файла |
Примечания
- Двоичные файлы (PDF, изображения, архивы) обрабатываются корректно.
- Имя файла извлекается из заголовка
Content-Disposition(filenameилиfilename*=UTF-8''...); если его нет, используется последний сегмент пути URL. - Отмена выполняется автоматически с помощью встроенной в htmx обработки прерывания запроса.
- Для
HX-Downloadиндикаторы и отключённые элементы корректно очищаются после завершения исходного запроса — дополнительный запрос выполняется независимо.
Licensed under the Zero-Clause BSD License.
https://four.htmx.org/extensions/hx-download/