This commit is contained in:
Zack Pollard 2025-08-04 12:00:35 +01:00
parent 8108f50c4e
commit 93aaf92c55
3 changed files with 33 additions and 0 deletions

View File

@ -16,7 +16,9 @@ export class AssetUploadInterceptor implements NestInterceptor {
const res = context.switchToHttp().getResponse<Response<AssetMediaResponseDto>>(); const res = context.switchToHttp().getResponse<Response<AssetMediaResponseDto>>();
const checksum = fromMaybeArray(req.headers[ImmichHeader.Checksum]); const checksum = fromMaybeArray(req.headers[ImmichHeader.Checksum]);
console.log('AssetUploadInterceptor checksum:', checksum);
const response = await this.service.getUploadAssetIdByChecksum(req.user, checksum); const response = await this.service.getUploadAssetIdByChecksum(req.user, checksum);
console.log('AssetUploadInterceptor response:', response);
if (response) { if (response) {
res.status(200); res.status(200);
return of({ status: AssetMediaStatus.DUPLICATE, id: response.id }); return of({ status: AssetMediaStatus.DUPLICATE, id: response.id });

View File

@ -103,6 +103,24 @@ export class FileUploadInterceptor implements NestInterceptor {
} }
private filename(request: AuthRequest, file: Express.Multer.File, callback: DiskStorageCallback) { private filename(request: AuthRequest, file: Express.Multer.File, callback: DiskStorageCallback) {
console.log('File upload started:', file.originalname);
// @ts-expect-error abc
request.emit = (eventName: string) => {
console.log('File upload event emitted:', eventName);
};
request.on('close', () => {
console.log('Request closed');
});
request.on('aborted', () => {
console.log('Request aborted, cleaning up file');
this.defaultStorage._removeFile(request, file, (error) => {
if (error) {
this.logger.warn('Request aborted, failed to cleanup file', error);
} else {
this.logger.log('Request aborted, file cleaned up successfully');
}
});
});
return callbackify( return callbackify(
() => this.assetService.getUploadFilename(asRequest(request, file)), () => this.assetService.getUploadFilename(asRequest(request, file)),
callback as Callback<string>, callback as Callback<string>,
@ -128,8 +146,15 @@ export class FileUploadInterceptor implements NestInterceptor {
const hash = createHash('sha1'); const hash = createHash('sha1');
file.stream.on('data', (chunk) => hash.update(chunk)); file.stream.on('data', (chunk) => hash.update(chunk));
file.stream.on('error', (error) => {
this.logger.warn('Stream error while uploading file, cleaning up', error);
this.assetService.onUploadError(request, file).catch(this.logger.error);
callback(error);
});
console.log('File upload started:', file.originalname);
this.defaultStorage._handleFile(request, file, (error, info) => { this.defaultStorage._handleFile(request, file, (error, info) => {
if (error) { if (error) {
console.error('Error handling file upload:', error);
hash.destroy(); hash.destroy();
callback(error); callback(error);
} else { } else {

View File

@ -131,6 +131,7 @@ export class AssetMediaService extends BaseService {
sidecarFile?: UploadFile, sidecarFile?: UploadFile,
): Promise<AssetMediaResponseDto> { ): Promise<AssetMediaResponseDto> {
try { try {
console.log(`Uploading asset: ${file.originalPath}, size: ${file.size}`);
await this.requireAccess({ await this.requireAccess({
auth, auth,
permission: Permission.AssetUpload, permission: Permission.AssetUpload,
@ -138,20 +139,25 @@ export class AssetMediaService extends BaseService {
ids: [auth.user.id], ids: [auth.user.id],
}); });
console.log(`User quota: ${auth.user.quotaSizeInBytes}, usage: ${auth.user.quotaUsageInBytes}`);
this.requireQuota(auth, file.size); this.requireQuota(auth, file.size);
console.log(`Asset type: ${file.originalName}, checksum: ${file.checksum}`);
if (dto.livePhotoVideoId) { if (dto.livePhotoVideoId) {
await onBeforeLink( await onBeforeLink(
{ asset: this.assetRepository, event: this.eventRepository }, { asset: this.assetRepository, event: this.eventRepository },
{ userId: auth.user.id, livePhotoVideoId: dto.livePhotoVideoId }, { userId: auth.user.id, livePhotoVideoId: dto.livePhotoVideoId },
); );
} }
console.log(`Creating asset with deviceAssetId: ${dto.deviceAssetId}, deviceId: ${dto.deviceId}`);
const asset = await this.create(auth.user.id, dto, file, sidecarFile); const asset = await this.create(auth.user.id, dto, file, sidecarFile);
console.log(`Asset created with id: ${asset.id}, originalPath: ${asset.originalPath}`);
await this.userRepository.updateUsage(auth.user.id, file.size); await this.userRepository.updateUsage(auth.user.id, file.size);
return { id: asset.id, status: AssetMediaStatus.CREATED }; return { id: asset.id, status: AssetMediaStatus.CREATED };
} catch (error: any) { } catch (error: any) {
console.log(`Error uploading asset: ${error.message}, ${file.originalPath}`, error);
return this.handleUploadError(error, auth, file, sidecarFile); return this.handleUploadError(error, auth, file, sidecarFile);
} }
} }