From 6335b3bd3ca553ce8ed73a72ada63b62ba9b8c01 Mon Sep 17 00:00:00 2001 From: Maksim Eltyshev Date: Fri, 30 Jan 2026 21:53:53 +0100 Subject: [PATCH] fix: Enhance response headers for file attachments --- .../file-attachments/download-thumbnail.js | 22 +++++++++++++--- .../controllers/file-attachments/download.js | 25 ++++++++++++++++--- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/server/api/controllers/file-attachments/download-thumbnail.js b/server/api/controllers/file-attachments/download-thumbnail.js index 7ea2866e..92e4d2d4 100644 --- a/server/api/controllers/file-attachments/download-thumbnail.js +++ b/server/api/controllers/file-attachments/download-thumbnail.js @@ -77,16 +77,32 @@ module.exports = { const fileManager = sails.hooks['file-manager'].getInstance(); let readStream; + let headers; + try { - readStream = await fileManager.read( + [readStream, headers] = await fileManager.read( `${sails.config.custom.attachmentsPathSegment}/${attachment.data.uploadedFileId}/thumbnails/${inputs.fileName}.${inputs.fileExtension}`, + { + withHeaders: true, + }, ); } catch (error) { throw Errors.FILE_ATTACHMENT_NOT_FOUND; } - this.res.type(attachment.data.mimeType); - this.res.set('Cache-Control', 'private, max-age=86400, no-transform'); // TODO: move to config + this.res.set({ + ...headers, + 'Content-Type': attachment.data.mimeType, + 'Cache-Control': 'private, max-age=86400, no-transform', // TODO: move to config + }); + + readStream.on('error', () => { + if (this.res.headersSent) { + this.res.destroy(); + } else { + throw Errors.FILE_ATTACHMENT_NOT_FOUND; + } + }); return exits.success(readStream); }, diff --git a/server/api/controllers/file-attachments/download.js b/server/api/controllers/file-attachments/download.js index 70442294..9b1694fc 100644 --- a/server/api/controllers/file-attachments/download.js +++ b/server/api/controllers/file-attachments/download.js @@ -70,21 +70,38 @@ module.exports = { const fileManager = sails.hooks['file-manager'].getInstance(); let readStream; + let headers; + try { - readStream = await fileManager.read( + [readStream, headers] = await fileManager.read( `${sails.config.custom.attachmentsPathSegment}/${attachment.data.uploadedFileId}/${attachment.data.filename}`, + { + withHeaders: true, + }, ); } catch (error) { throw Errors.FILE_ATTACHMENT_NOT_FOUND; } if (attachment.data.mimeType) { - this.res.type(attachment.data.mimeType); + headers['Content-Type'] = attachment.data.mimeType; } if (!INLINE_MIME_TYPES_SET.has(attachment.data.mimeType) && !attachment.data.image) { - this.res.set('Content-Disposition', 'attachment'); + headers['Content-Disposition'] = 'attachment'; } - this.res.set('Cache-Control', 'private, max-age=86400, no-transform'); // TODO: move to config + + this.res.set({ + ...headers, + 'Cache-Control': 'private, max-age=86400, no-transform', // TODO: move to config + }); + + readStream.on('error', () => { + if (this.res.headersSent) { + this.res.destroy(); + } else { + throw Errors.FILE_ATTACHMENT_NOT_FOUND; + } + }); return exits.success(readStream); },