Skip to content

Commit 61cee45

Browse files
committed
Handle downloads in Component.js
1 parent bd6b8bd commit 61cee45

File tree

1 file changed

+47
-2
lines changed
  • src/LiveComponent/assets/src/Component

1 file changed

+47
-2
lines changed

src/LiveComponent/assets/src/Component/index.ts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,15 +300,60 @@ export default class Component {
300300

301301
this.backendRequest.promise.then(async (response) => {
302302
const backendResponse = new BackendResponse(response);
303-
const html = await backendResponse.getBody();
304303

305304
// clear sent files inputs
306305
for (const input of Object.values(this.pendingFiles)) {
307306
input.value = '';
308307
}
309308

310-
// if the response does not contain a component, render as an error
311309
const headers = backendResponse.response.headers;
310+
if (headers.get('X-Live-Download')) {
311+
if (
312+
!(
313+
headers.get('Content-Disposition')?.includes('attachment') ||
314+
headers.get('Content-Disposition')?.includes('inline')
315+
) ||
316+
!headers.get('Content-Disposition')?.includes('filename=')
317+
) {
318+
throw new Error('Invalid LiveDownload response');
319+
}
320+
321+
const fileSize = Number.parseInt(headers.get('Content-Length') || '0');
322+
if (fileSize > 10000000) {
323+
throw new Error('File is too large to download (10MB limit)');
324+
}
325+
326+
const fileName = headers.get('Content-Disposition')?.split('filename=')[1];
327+
if (!fileName) {
328+
throw new Error('No filename found in Content-Disposition header');
329+
}
330+
331+
const blob = await backendResponse.getBlob();
332+
const link = Object.assign(window.document.createElement('a'), {
333+
target: '_blank',
334+
style: 'display: none',
335+
href: window.URL.createObjectURL(blob),
336+
download: fileName,
337+
});
338+
this.element.appendChild(link);
339+
link.click();
340+
this.element.removeChild(link);
341+
342+
this.backendRequest = null;
343+
thisPromiseResolve(backendResponse);
344+
345+
// do we already have another request pending?
346+
if (this.isRequestPending) {
347+
this.isRequestPending = false;
348+
this.performRequest();
349+
}
350+
351+
return response;
352+
}
353+
354+
const html = await backendResponse.getBody();
355+
356+
// if the response does not contain a component, render as an error
312357
if (
313358
!headers.get('Content-Type')?.includes('application/vnd.live-component+html') &&
314359
!headers.get('X-Live-Redirect')

0 commit comments

Comments
 (0)