mirror of
https://github.com/immich-app/immich
synced 2025-11-14 17:36:12 +00:00
fix: iOS portrait photo saved as jpg extension (#21388)
remove bad merged settings remove console log
This commit is contained in:
parent
28edf5664d
commit
4f7702c6bf
5 changed files with 36 additions and 21 deletions
|
|
@ -12,7 +12,7 @@ import { AuthRequest } from 'src/middleware/auth.guard';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { AssetMediaService } from 'src/services/asset-media.service';
|
import { AssetMediaService } from 'src/services/asset-media.service';
|
||||||
import { ImmichFile, UploadFile, UploadFiles } from 'src/types';
|
import { ImmichFile, UploadFile, UploadFiles } from 'src/types';
|
||||||
import { asRequest, mapToUploadFile } from 'src/utils/asset.util';
|
import { asUploadRequest, mapToUploadFile } from 'src/utils/asset.util';
|
||||||
|
|
||||||
export function getFile(files: UploadFiles, property: 'assetData' | 'sidecarData') {
|
export function getFile(files: UploadFiles, property: 'assetData' | 'sidecarData') {
|
||||||
const file = files[property]?.[0];
|
const file = files[property]?.[0];
|
||||||
|
|
@ -99,18 +99,21 @@ export class FileUploadInterceptor implements NestInterceptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fileFilter(request: AuthRequest, file: Express.Multer.File, callback: multer.FileFilterCallback) {
|
private fileFilter(request: AuthRequest, file: Express.Multer.File, callback: multer.FileFilterCallback) {
|
||||||
return callbackify(() => this.assetService.canUploadFile(asRequest(request, file)), callback);
|
return callbackify(() => this.assetService.canUploadFile(asUploadRequest(request, file)), callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private filename(request: AuthRequest, file: Express.Multer.File, callback: DiskStorageCallback) {
|
private filename(request: AuthRequest, file: Express.Multer.File, callback: DiskStorageCallback) {
|
||||||
return callbackify(
|
return callbackify(
|
||||||
() => this.assetService.getUploadFilename(asRequest(request, file)),
|
() => this.assetService.getUploadFilename(asUploadRequest(request, file)),
|
||||||
callback as Callback<string>,
|
callback as Callback<string>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private destination(request: AuthRequest, file: Express.Multer.File, callback: DiskStorageCallback) {
|
private destination(request: AuthRequest, file: Express.Multer.File, callback: DiskStorageCallback) {
|
||||||
return callbackify(() => this.assetService.getUploadFolder(asRequest(request, file)), callback as Callback<string>);
|
return callbackify(
|
||||||
|
() => this.assetService.getUploadFolder(asUploadRequest(request, file)),
|
||||||
|
callback as Callback<string>,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleFile(request: AuthRequest, file: Express.Multer.File, callback: Callback<Partial<ImmichFile>>) {
|
private handleFile(request: AuthRequest, file: Express.Multer.File, callback: Callback<Partial<ImmichFile>>) {
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ const file1 = Buffer.from('d2947b871a706081be194569951b7db246907957', 'hex');
|
||||||
const uploadFile = {
|
const uploadFile = {
|
||||||
nullAuth: {
|
nullAuth: {
|
||||||
auth: null,
|
auth: null,
|
||||||
|
body: {},
|
||||||
fieldName: UploadFieldName.ASSET_DATA,
|
fieldName: UploadFieldName.ASSET_DATA,
|
||||||
file: {
|
file: {
|
||||||
uuid: 'random-uuid',
|
uuid: 'random-uuid',
|
||||||
|
|
@ -37,6 +38,7 @@ const uploadFile = {
|
||||||
filename: (fieldName: UploadFieldName, filename: string) => {
|
filename: (fieldName: UploadFieldName, filename: string) => {
|
||||||
return {
|
return {
|
||||||
auth: authStub.admin,
|
auth: authStub.admin,
|
||||||
|
body: {},
|
||||||
fieldName,
|
fieldName,
|
||||||
file: {
|
file: {
|
||||||
uuid: 'random-uuid',
|
uuid: 'random-uuid',
|
||||||
|
|
@ -897,7 +899,10 @@ describe(AssetMediaService.name, () => {
|
||||||
|
|
||||||
describe('onUploadError', () => {
|
describe('onUploadError', () => {
|
||||||
it('should queue a job to delete the uploaded file', async () => {
|
it('should queue a job to delete the uploaded file', async () => {
|
||||||
const request = { user: authStub.user1 } as AuthRequest;
|
const request = {
|
||||||
|
body: {},
|
||||||
|
user: authStub.user1,
|
||||||
|
} as AuthRequest;
|
||||||
|
|
||||||
const file = {
|
const file = {
|
||||||
fieldname: UploadFieldName.ASSET_DATA,
|
fieldname: UploadFieldName.ASSET_DATA,
|
||||||
|
|
|
||||||
|
|
@ -24,20 +24,14 @@ import { AuthDto } from 'src/dtos/auth.dto';
|
||||||
import { AssetStatus, AssetType, AssetVisibility, CacheControl, JobName, Permission, StorageFolder } from 'src/enum';
|
import { AssetStatus, AssetType, AssetVisibility, CacheControl, JobName, Permission, StorageFolder } from 'src/enum';
|
||||||
import { AuthRequest } from 'src/middleware/auth.guard';
|
import { AuthRequest } from 'src/middleware/auth.guard';
|
||||||
import { BaseService } from 'src/services/base.service';
|
import { BaseService } from 'src/services/base.service';
|
||||||
import { UploadFile } from 'src/types';
|
import { UploadFile, UploadRequest } from 'src/types';
|
||||||
import { requireUploadAccess } from 'src/utils/access';
|
import { requireUploadAccess } from 'src/utils/access';
|
||||||
import { asRequest, getAssetFiles, onBeforeLink } from 'src/utils/asset.util';
|
import { asUploadRequest, getAssetFiles, onBeforeLink } from 'src/utils/asset.util';
|
||||||
import { isAssetChecksumConstraint } from 'src/utils/database';
|
import { isAssetChecksumConstraint } from 'src/utils/database';
|
||||||
import { getFilenameExtension, getFileNameWithoutExtension, ImmichFileResponse } from 'src/utils/file';
|
import { getFilenameExtension, getFileNameWithoutExtension, ImmichFileResponse } from 'src/utils/file';
|
||||||
import { mimeTypes } from 'src/utils/mime-types';
|
import { mimeTypes } from 'src/utils/mime-types';
|
||||||
import { fromChecksum } from 'src/utils/request';
|
import { fromChecksum } from 'src/utils/request';
|
||||||
|
|
||||||
interface UploadRequest {
|
|
||||||
auth: AuthDto | null;
|
|
||||||
fieldName: UploadFieldName;
|
|
||||||
file: UploadFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AssetMediaRedirectResponse {
|
export interface AssetMediaRedirectResponse {
|
||||||
targetSize: AssetMediaSize | 'original';
|
targetSize: AssetMediaSize | 'original';
|
||||||
}
|
}
|
||||||
|
|
@ -89,15 +83,15 @@ export class AssetMediaService extends BaseService {
|
||||||
throw new BadRequestException(`Unsupported file type ${filename}`);
|
throw new BadRequestException(`Unsupported file type ${filename}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getUploadFilename({ auth, fieldName, file }: UploadRequest): string {
|
getUploadFilename({ auth, fieldName, file, body }: UploadRequest): string {
|
||||||
requireUploadAccess(auth);
|
requireUploadAccess(auth);
|
||||||
|
|
||||||
const originalExtension = extname(file.originalName);
|
const extension = extname(body.filename || file.originalName);
|
||||||
|
|
||||||
const lookup = {
|
const lookup = {
|
||||||
[UploadFieldName.ASSET_DATA]: originalExtension,
|
[UploadFieldName.ASSET_DATA]: extension,
|
||||||
[UploadFieldName.SIDECAR_DATA]: '.xmp',
|
[UploadFieldName.SIDECAR_DATA]: '.xmp',
|
||||||
[UploadFieldName.PROFILE_DATA]: originalExtension,
|
[UploadFieldName.PROFILE_DATA]: extension,
|
||||||
};
|
};
|
||||||
|
|
||||||
return sanitize(`${file.uuid}${lookup[fieldName]}`);
|
return sanitize(`${file.uuid}${lookup[fieldName]}`);
|
||||||
|
|
@ -117,8 +111,8 @@ export class AssetMediaService extends BaseService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async onUploadError(request: AuthRequest, file: Express.Multer.File) {
|
async onUploadError(request: AuthRequest, file: Express.Multer.File) {
|
||||||
const uploadFilename = this.getUploadFilename(asRequest(request, file));
|
const uploadFilename = this.getUploadFilename(asUploadRequest(request, file));
|
||||||
const uploadFolder = this.getUploadFolder(asRequest(request, file));
|
const uploadFolder = this.getUploadFolder(asUploadRequest(request, file));
|
||||||
const uploadPath = `${uploadFolder}/${uploadFilename}`;
|
const uploadPath = `${uploadFolder}/${uploadFilename}`;
|
||||||
|
|
||||||
await this.jobRepository.queue({ name: JobName.FileDelete, data: { files: [uploadPath] } });
|
await this.jobRepository.queue({ name: JobName.FileDelete, data: { files: [uploadPath] } });
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import { SystemConfig } from 'src/config';
|
import { SystemConfig } from 'src/config';
|
||||||
import { VECTOR_EXTENSIONS } from 'src/constants';
|
import { VECTOR_EXTENSIONS } from 'src/constants';
|
||||||
|
import { UploadFieldName } from 'src/dtos/asset-media.dto';
|
||||||
|
import { AuthDto } from 'src/dtos/auth.dto';
|
||||||
import {
|
import {
|
||||||
AssetMetadataKey,
|
AssetMetadataKey,
|
||||||
AssetOrder,
|
AssetOrder,
|
||||||
|
|
@ -408,6 +410,16 @@ export interface UploadFile {
|
||||||
size: number;
|
size: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type UploadRequest = {
|
||||||
|
auth: AuthDto | null;
|
||||||
|
fieldName: UploadFieldName;
|
||||||
|
file: UploadFile;
|
||||||
|
body: {
|
||||||
|
filename?: string;
|
||||||
|
[key: string]: unknown;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export interface UploadFiles {
|
export interface UploadFiles {
|
||||||
assetData: ImmichFile[];
|
assetData: ImmichFile[];
|
||||||
sidecarData: ImmichFile[];
|
sidecarData: ImmichFile[];
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import { AccessRepository } from 'src/repositories/access.repository';
|
||||||
import { AssetRepository } from 'src/repositories/asset.repository';
|
import { AssetRepository } from 'src/repositories/asset.repository';
|
||||||
import { EventRepository } from 'src/repositories/event.repository';
|
import { EventRepository } from 'src/repositories/event.repository';
|
||||||
import { PartnerRepository } from 'src/repositories/partner.repository';
|
import { PartnerRepository } from 'src/repositories/partner.repository';
|
||||||
import { IBulkAsset, ImmichFile, UploadFile } from 'src/types';
|
import { IBulkAsset, ImmichFile, UploadFile, UploadRequest } from 'src/types';
|
||||||
import { checkAccess } from 'src/utils/access';
|
import { checkAccess } from 'src/utils/access';
|
||||||
|
|
||||||
export const getAssetFile = (files: AssetFile[], type: AssetFileType | GeneratedImageType) => {
|
export const getAssetFile = (files: AssetFile[], type: AssetFileType | GeneratedImageType) => {
|
||||||
|
|
@ -190,9 +190,10 @@ export function mapToUploadFile(file: ImmichFile): UploadFile {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const asRequest = (request: AuthRequest, file: Express.Multer.File) => {
|
export const asUploadRequest = (request: AuthRequest, file: Express.Multer.File): UploadRequest => {
|
||||||
return {
|
return {
|
||||||
auth: request.user || null,
|
auth: request.user || null,
|
||||||
|
body: request.body,
|
||||||
fieldName: file.fieldname as UploadFieldName,
|
fieldName: file.fieldname as UploadFieldName,
|
||||||
file: mapToUploadFile(file as ImmichFile),
|
file: mapToUploadFile(file as ImmichFile),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue