Skip to content

Commit 5a6598d

Browse files
authored
Merge pull request #44 from evolution-foundation/fix/EVO-999
fix(media): force file download via fetch+blob instead of window.open (EVO-999)
2 parents dcb648a + b5b4940 commit 5a6598d

7 files changed

Lines changed: 63 additions & 14 deletions

File tree

src/components/chat/messages/MessageFile.tsx

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,35 @@ interface MessageFileProps {
1313
const 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

src/i18n/locales/en/chat.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,12 @@
6161
"messageFile": {
6262
"fileFallback": "file",
6363
"unknownSize": "Unknown size",
64-
"fileFallbackTitle": "File"
64+
"fileFallbackTitle": "File",
65+
"downloadFallbackOpenedInNewTab": "File opened in new tab",
66+
"downloadFallbackReason": {
67+
"serverError": "Server returned {{status}} — could not download directly.",
68+
"network": "Network error or CORS block — could not download directly."
69+
}
6570
},
6671
"messageImage": {
6772
"downloadStarted": "Download started",

src/i18n/locales/es/chat.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@
6060
"messageFile": {
6161
"fileFallback": "archivo",
6262
"unknownSize": "Tamaño desconocido",
63-
"fileFallbackTitle": "Archivo"
63+
"fileFallbackTitle": "Archivo",
64+
"downloadFallbackOpenedInNewTab": "Archivo abierto en nueva pestaña",
65+
"downloadFallbackReason": {
66+
"serverError": "El servidor devolvió {{status}} — no se pudo descargar directamente.",
67+
"network": "Error de red o bloqueo de CORS — no se pudo descargar directamente."
68+
}
6469
},
6570
"messageImage": {
6671
"downloadStarted": "Descarga iniciada",

src/i18n/locales/fr/chat.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@
6060
"messageFile": {
6161
"fileFallback": "fichier",
6262
"unknownSize": "Taille inconnue",
63-
"fileFallbackTitle": "Fichier"
63+
"fileFallbackTitle": "Fichier",
64+
"downloadFallbackOpenedInNewTab": "Fichier ouvert dans un nouvel onglet",
65+
"downloadFallbackReason": {
66+
"serverError": "Le serveur a renvoyé {{status}} — impossible de télécharger directement.",
67+
"network": "Erreur réseau ou blocage CORS — impossible de télécharger directement."
68+
}
6469
},
6570
"messageImage": {
6671
"downloadStarted": "Téléchargement démarré",

src/i18n/locales/it/chat.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@
6060
"messageFile": {
6161
"fileFallback": "file",
6262
"unknownSize": "Dimensione sconosciuta",
63-
"fileFallbackTitle": "File"
63+
"fileFallbackTitle": "File",
64+
"downloadFallbackOpenedInNewTab": "File aperto in una nuova scheda",
65+
"downloadFallbackReason": {
66+
"serverError": "Il server ha restituito {{status}} — impossibile scaricare direttamente.",
67+
"network": "Errore di rete o blocco CORS — impossibile scaricare direttamente."
68+
}
6469
},
6570
"messageImage": {
6671
"downloadStarted": "Download avviato",

src/i18n/locales/pt-BR/chat.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,12 @@
6161
"messageFile": {
6262
"fileFallback": "arquivo",
6363
"unknownSize": "Tamanho desconhecido",
64-
"fileFallbackTitle": "Arquivo"
64+
"fileFallbackTitle": "Arquivo",
65+
"downloadFallbackOpenedInNewTab": "Arquivo aberto em nova aba",
66+
"downloadFallbackReason": {
67+
"serverError": "Servidor retornou {{status}} — não foi possível baixar diretamente.",
68+
"network": "Falha de rede ou bloqueio de CORS — não foi possível baixar diretamente."
69+
}
6570
},
6671
"messageImage": {
6772
"downloadStarted": "Download iniciado",

src/i18n/locales/pt/chat.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@
6060
"messageFile": {
6161
"fileFallback": "arquivo",
6262
"unknownSize": "Tamanho desconhecido",
63-
"fileFallbackTitle": "Arquivo"
63+
"fileFallbackTitle": "Arquivo",
64+
"downloadFallbackOpenedInNewTab": "Ficheiro aberto em nova aba",
65+
"downloadFallbackReason": {
66+
"serverError": "O servidor retornou {{status}} — não foi possível descarregar diretamente.",
67+
"network": "Falha de rede ou bloqueio de CORS — não foi possível descarregar diretamente."
68+
}
6469
},
6570
"messageImage": {
6671
"downloadStarted": "Download iniciado",

0 commit comments

Comments
 (0)