64 lines
2.4 KiB
JavaScript
64 lines
2.4 KiB
JavaScript
// Copied from: https://github.com/dakixr/htmx-download/blob/main/htmx-download.js
|
|
htmx.defineExtension('htmx-download', {
|
|
onEvent: function(name, evt) {
|
|
|
|
if (name === 'htmx:beforeRequest') {
|
|
// Set the responseType to 'arraybuffer' to handle binary data
|
|
evt.detail.xhr.responseType = 'arraybuffer';
|
|
}
|
|
|
|
if (name === 'htmx:beforeSwap') {
|
|
const xhr = evt.detail.xhr;
|
|
|
|
if (xhr.status === 200) {
|
|
// Parse headers
|
|
const headers = {};
|
|
const headerStr = xhr.getAllResponseHeaders();
|
|
const headerArr = headerStr.trim().split(/[\r\n]+/);
|
|
headerArr.forEach((line) => {
|
|
const parts = line.split(": ");
|
|
const header = parts.shift().toLowerCase();
|
|
const value = parts.join(": ");
|
|
headers[header] = value;
|
|
});
|
|
|
|
// Extract filename
|
|
let filename = 'downloaded_file.xlsx';
|
|
if (headers['content-disposition']) {
|
|
const filenameMatch = headers['content-disposition'].match(/filename\*?=(?:UTF-8'')?"?([^;\n"]+)/i);
|
|
if (filenameMatch && filenameMatch[1]) {
|
|
filename = decodeURIComponent(filenameMatch[1].replace(/['"]/g, ''));
|
|
}
|
|
}
|
|
|
|
// Determine MIME type
|
|
const mimetype = headers['content-type'] || 'application/octet-stream';
|
|
|
|
// Create Blob
|
|
const blob = new Blob([xhr.response], { type: mimetype });
|
|
const url = URL.createObjectURL(blob);
|
|
|
|
// Trigger download
|
|
const link = document.createElement("a");
|
|
link.style.display = "none";
|
|
link.href = url;
|
|
link.download = filename;
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
|
|
// Cleanup
|
|
setTimeout(() => {
|
|
URL.revokeObjectURL(url);
|
|
link.remove();
|
|
}, 100);
|
|
|
|
} else {
|
|
console.warn(`[htmx-download] Unexpected response status: ${xhr.status}`);
|
|
}
|
|
|
|
// Prevent htmx from swapping content
|
|
evt.detail.shouldSwap = false;
|
|
}
|
|
},
|
|
});
|