@@ -13,16 +13,35 @@ interface MessageFileProps {
1313const MessageFile : React . FC < MessageFileProps > = ( { attachments } ) => {
1414 const { t } = useLanguage ( 'chat' ) ;
1515
16- const downloadFile = ( attachment : Attachment ) => {
17- const result = openAttachmentInNewTab ( {
18- url : attachment . data_url ,
19- filename : attachment . fallback_title || t ( 'messages.messageFile.fileFallback' ) ,
20- } ) ;
16+ const downloadFile = async ( attachment : Attachment ) => {
17+ const url = attachment . data_url ?. trim ( ) ;
18+ if ( ! url ) return ;
2119
22- if ( result === 'download-fallback' ) {
23- toast . info ( t ( 'messages.messageImage.downloadStarted' ) , {
24- description : attachment . fallback_title || t ( 'messages.messageFile.fileFallbackTitle' ) ,
20+ const filename = attachment . fallback_title || t ( 'messages.messageFile.fileFallback' ) ;
21+
22+ try {
23+ const response = await fetch ( url , { mode : 'cors' } ) ;
24+ if ( ! response . ok ) {
25+ console . warn ( '[MessageFile] non-ok response:' , response . status , url ) ;
26+ toast . warning ( t ( 'messages.messageFile.downloadFallbackOpenedInNewTab' ) , {
27+ description : t ( 'messages.messageFile.downloadFallbackReason.serverError' , { status : response . status } ) ,
28+ } ) ;
29+ openAttachmentInNewTab ( { url, filename } ) ;
30+ return ;
31+ }
32+ const blob = await response . blob ( ) ;
33+ const blobUrl = URL . createObjectURL ( blob ) ;
34+ const link = document . createElement ( 'a' ) ;
35+ link . href = blobUrl ;
36+ link . download = filename ;
37+ link . click ( ) ;
38+ setTimeout ( ( ) => URL . revokeObjectURL ( blobUrl ) , 0 ) ;
39+ } catch ( err ) {
40+ console . warn ( '[MessageFile] download fallback after fetch error:' , err ) ;
41+ toast . warning ( t ( 'messages.messageFile.downloadFallbackOpenedInNewTab' ) , {
42+ description : t ( 'messages.messageFile.downloadFallbackReason.network' ) ,
2543 } ) ;
44+ openAttachmentInNewTab ( { url, filename } ) ;
2645 }
2746 } ;
2847
0 commit comments