diff --git a/server/src/services/asset-media.service.spec.ts b/server/src/services/asset-media.service.spec.ts index d68140367d702..da7e23be54412 100644 --- a/server/src/services/asset-media.service.spec.ts +++ b/server/src/services/asset-media.service.spec.ts @@ -571,6 +571,7 @@ describe(AssetMediaService.name, () => { path: '/path/to/preview.jpg', cacheControl: CacheControl.PRIVATE_WITH_CACHE, contentType: 'image/jpeg', + fileName: 'asset-id_thumbnail.jpg', }), ); }); @@ -585,6 +586,7 @@ describe(AssetMediaService.name, () => { path: assetStub.image.files[0].path, cacheControl: CacheControl.PRIVATE_WITH_CACHE, contentType: 'image/jpeg', + fileName: 'asset-id_preview.jpg', }), ); }); @@ -599,6 +601,7 @@ describe(AssetMediaService.name, () => { path: assetStub.image.files[1].path, cacheControl: CacheControl.PRIVATE_WITH_CACHE, contentType: 'application/octet-stream', + fileName: 'asset-id_thumbnail.ext', }), ); }); diff --git a/server/src/services/asset-media.service.ts b/server/src/services/asset-media.service.ts index 2424c93e44a15..e96d1fd0a6f4b 100644 --- a/server/src/services/asset-media.service.ts +++ b/server/src/services/asset-media.service.ts @@ -27,7 +27,7 @@ import { AuthRequest } from 'src/middleware/auth.guard'; import { BaseService } from 'src/services/base.service'; import { requireUploadAccess } from 'src/utils/access'; import { asRequest, getAssetFiles, onBeforeLink } from 'src/utils/asset.util'; -import { ImmichFileResponse } from 'src/utils/file'; +import { getFilenameExtension, getFileNameWithoutExtension, ImmichFileResponse } from 'src/utils/file'; import { mimeTypes } from 'src/utils/mime-types'; import { fromChecksum } from 'src/utils/request'; import { QueryFailedError } from 'typeorm'; @@ -217,8 +217,12 @@ export class AssetMediaService extends BaseService { if (!filepath) { throw new NotFoundException('Asset media not found'); } + let fileName = getFileNameWithoutExtension(asset.originalFileName); + fileName += `_${size}`; + fileName += getFilenameExtension(filepath); return new ImmichFileResponse({ + fileName, path: filepath, contentType: mimeTypes.lookup(filepath), cacheControl: CacheControl.PRIVATE_WITH_CACHE, diff --git a/server/src/utils/file.ts b/server/src/utils/file.ts index 3b26c3e1ba1e8..e979c2ad70872 100644 --- a/server/src/utils/file.ts +++ b/server/src/utils/file.ts @@ -24,6 +24,7 @@ export class ImmichFileResponse { public readonly path!: string; public readonly contentType!: string; public readonly cacheControl!: CacheControl; + public readonly fileName?: string; constructor(response: ImmichFileResponse) { Object.assign(this, response); @@ -56,6 +57,7 @@ export const sendFile = async ( } res.header('Content-Type', file.contentType); + if(file.fileName) {res.header('Content-Disposition', `inline; filename="${file.fileName}"`);} const options: SendFileOptions = { dotfiles: 'allow' }; if (!isAbsolute(file.path)) {