@@ -111,6 +111,9 @@ class BackendResponse {
111
111
}
112
112
return this . body ;
113
113
}
114
+ async getBlob ( ) {
115
+ return await this . response . blob ( ) ;
116
+ }
114
117
}
115
118
116
119
function getElementAsTagText ( element ) {
@@ -2119,11 +2122,43 @@ class Component {
2119
2122
this . isRequestPending = false ;
2120
2123
this . backendRequest . promise . then ( async ( response ) => {
2121
2124
const backendResponse = new BackendResponse ( response ) ;
2122
- const html = await backendResponse . getBody ( ) ;
2123
2125
for ( const input of Object . values ( this . pendingFiles ) ) {
2124
2126
input . value = '' ;
2125
2127
}
2126
2128
const headers = backendResponse . response . headers ;
2129
+ if ( headers . get ( 'X-Live-Download' ) ) {
2130
+ if ( ! ( headers . get ( 'Content-Disposition' ) ?. includes ( 'attachment' ) ||
2131
+ headers . get ( 'Content-Disposition' ) ?. includes ( 'inline' ) ) ||
2132
+ ! headers . get ( 'Content-Disposition' ) ?. includes ( 'filename=' ) ) {
2133
+ throw new Error ( 'Invalid LiveDownload response' ) ;
2134
+ }
2135
+ const fileSize = Number . parseInt ( headers . get ( 'Content-Length' ) || '0' ) ;
2136
+ if ( fileSize > 10000000 ) {
2137
+ throw new Error ( 'File is too large to download (10MB limit)' ) ;
2138
+ }
2139
+ const fileName = headers . get ( 'Content-Disposition' ) ?. split ( 'filename=' ) [ 1 ] ;
2140
+ if ( ! fileName ) {
2141
+ throw new Error ( 'No filename found in Content-Disposition header' ) ;
2142
+ }
2143
+ const blob = await backendResponse . getBlob ( ) ;
2144
+ const link = Object . assign ( window . document . createElement ( 'a' ) , {
2145
+ target : '_blank' ,
2146
+ style : 'display: none' ,
2147
+ href : window . URL . createObjectURL ( blob ) ,
2148
+ download : fileName ,
2149
+ } ) ;
2150
+ this . element . appendChild ( link ) ;
2151
+ link . click ( ) ;
2152
+ this . element . removeChild ( link ) ;
2153
+ this . backendRequest = null ;
2154
+ thisPromiseResolve ( backendResponse ) ;
2155
+ if ( this . isRequestPending ) {
2156
+ this . isRequestPending = false ;
2157
+ this . performRequest ( ) ;
2158
+ }
2159
+ return response ;
2160
+ }
2161
+ const html = await backendResponse . getBody ( ) ;
2127
2162
if ( ! headers . get ( 'Content-Type' ) ?. includes ( 'application/vnd.live-component+html' ) &&
2128
2163
! headers . get ( 'X-Live-Redirect' ) ) {
2129
2164
const controls = { displayError : true } ;
0 commit comments