diff --git a/.changeset/dull-ducks-shake.md b/.changeset/dull-ducks-shake.md new file mode 100644 index 0000000000..ed56fb732a --- /dev/null +++ b/.changeset/dull-ducks-shake.md @@ -0,0 +1,5 @@ +--- +'@directus/api': patch +--- + +Fixed filename_disk extension not getting updated when replacing an image with another file extension diff --git a/api/src/services/files.test.ts b/api/src/services/files.test.ts index 5906b72bac..b491218201 100644 --- a/api/src/services/files.test.ts +++ b/api/src/services/files.test.ts @@ -149,6 +149,56 @@ describe('Integration Tests', () => { { emitEvents: false }, ); }); + + it('should update the `filename_disk` extension to the correct mimetype', async () => { + tracker.on + .select( + 'select "folder", "filename_download", "filename_disk", "title", "description", "metadata" from "directus_files" where "id" = ?', + ) + .response(null); + + const mockDataJPG = { + storage: 'local', + type: 'image/jpeg', + filename_download: 'test.jpg', + }; + + const mockDataPNG = { + storage: 'local', + type: 'image/png', + filename_download: 'test.png', + }; + + const mockDate = new Date(); + + vi.setSystemTime(mockDate); + + await service.uploadOne(new PassThrough(), mockDataJPG); + + expect(superUpdateOne).toHaveBeenCalledWith( + sample.id, + expect.objectContaining({ + ...mockDataJPG, + uploaded_on: mockDate.toISOString(), + filename_disk: `${sample.id}.jpg`, + }), + { emitEvents: false }, + ); + + await service.uploadOne(new PassThrough(), mockDataPNG); + + expect(superUpdateOne).toHaveBeenCalledWith( + sample.id, + expect.objectContaining({ + ...mockDataPNG, + uploaded_on: mockDate.toISOString(), + filename_disk: `${sample.id}.png`, + }), + { emitEvents: false }, + ); + + vi.useRealTimers(); + }); }); }); }); diff --git a/api/src/services/files.ts b/api/src/services/files.ts index d9853a74fc..a220c857be 100644 --- a/api/src/services/files.ts +++ b/api/src/services/files.ts @@ -81,6 +81,11 @@ export class FilesService extends ItemsService { // The filename_disk is the FINAL filename on disk payload.filename_disk ||= primaryKey + (fileExtension || ''); + // If the filename_disk extension doesn't match the new mimetype, update it + if (isReplacement === true && path.extname(payload.filename_disk!) !== fileExtension) { + payload.filename_disk = primaryKey + (fileExtension || ''); + } + // Temp filename is used for replacements const tempFilenameDisk = 'temp_' + payload.filename_disk;