feat: deal with file upload size locally

This commit is contained in:
hexastack
2025-04-08 12:09:51 +01:00
parent beca726551
commit 8472e4a4fc
6 changed files with 82 additions and 0 deletions

View File

@@ -46,6 +46,7 @@ import { AttachmentGuard } from '../guards/attachment-ability.guard';
import { Attachment } from '../schemas/attachment.schema';
import { AttachmentService } from '../services/attachment.service';
import { AttachmentAccess, AttachmentCreatedByRef } from '../types';
import { attachmentSizeLimits } from '../utilities';
@UseInterceptors(CsrfInterceptor)
@Controller('attachment')
@@ -131,12 +132,28 @@ export class AttachmentController extends BaseController<Attachment> {
{
resourceRef,
access = AttachmentAccess.Public,
maxSize,
}: AttachmentContextParamDto,
): Promise<Attachment[]> {
if (!files || !Array.isArray(files?.file) || files.file.length === 0) {
throw new BadRequestException('No file was selected');
}
// Determine the size limit
const sizeLimit =
maxSize ??
attachmentSizeLimits[resourceRef] ??
config.parameters.maxUploadSize;
// Validate file sizes against the limit
for (const file of files.file) {
if (file.size > sizeLimit) {
throw new BadRequestException(
`File ${file.originalname} exceeds maximum size of ${sizeLimit} bytes`,
);
}
}
const userId = req.session?.passport?.user?.id;
if (!userId) {
throw new ForbiddenException(

View File

@@ -154,4 +154,12 @@ export class AttachmentContextParamDto {
@IsIn(Object.values(AttachmentAccess))
@IsOptional()
access?: AttachmentAccess;
@ApiPropertyOptional({
description: 'Maximum file size in bytes for this upload',
type: Number,
})
@IsNumber()
@IsOptional()
maxSize?: number;
}

View File

@@ -109,3 +109,26 @@ export const isAttachmentResourceRefArray = (
refList.every(isAttachmentResourceRef)
);
};
/**
* Retrieves the maximum size limit for a given resource reference.
*
* @param resourceRef - The resource reference to check.
* @returns The maximum size limit in bytes.
*/
export const attachmentSizeLimits: Partial<
Record<AttachmentResourceRef, number>
> = {
[AttachmentResourceRef.SettingAttachment]:
config.attachmentSizeLimits.settingAttachmentSizeLimit,
[AttachmentResourceRef.UserAvatar]:
config.attachmentSizeLimits.userAvatarSizeLimit,
[AttachmentResourceRef.SubscriberAvatar]:
config.attachmentSizeLimits.subscriberAvatarSizeLimit,
[AttachmentResourceRef.BlockAttachment]:
config.attachmentSizeLimits.blockAttachmentSizeLimit,
[AttachmentResourceRef.ContentAttachment]:
config.attachmentSizeLimits.contentAttachmentSizeLimit,
[AttachmentResourceRef.MessageAttachment]:
config.attachmentSizeLimits.messageAttachmentSizeLimit,
};

View File

@@ -194,4 +194,24 @@ export const config: Config = {
retentionReset: 24 * 60 * 60 * 1000, // 1 day
},
},
attachmentSizeLimits: {
settingAttachmentSizeLimit: process.env.SETTING_ATTACHMENT_MAX_SIZE_IN_BYTES
? Number(process.env.SETTING_ATTACHMENT_MAX_SIZE_IN_BYTES)
: 5 * 1024 * 1024,
userAvatarSizeLimit: process.env.USER_AVATAR_MAX_SIZE_IN_BYTES
? Number(process.env.USER_AVATAR_MAX_SIZE_IN_BYTES)
: 2 * 1024 * 1024,
subscriberAvatarSizeLimit: process.env.SUBSCRIBER_AVATAR_MAX_SIZE_IN_BYTES
? Number(process.env.SUBSCRIBER_AVATAR_MAX_SIZE_IN_BYTES)
: 2 * 1024 * 1024,
blockAttachmentSizeLimit: process.env.BLOCK_ATTACHMENT_MAX_SIZE_IN_BYTES
? Number(process.env.BLOCK_ATTACHMENT_MAX_SIZE_IN_BYTES)
: 5 * 1024 * 1024,
contentAttachmentSizeLimit: process.env.CONTENT_ATTACHMENT_MAX_SIZE_IN_BYTES
? Number(process.env.CONTENT_ATTACHMENT_MAX_SIZE_IN_BYTES)
: 10 * 1024 * 1024,
messageAttachmentSizeLimit: process.env.MESSAGE_ATTACHMENT_MAX_SIZE_IN_BYTES
? Number(process.env.MESSAGE_ATTACHMENT_MAX_SIZE_IN_BYTES)
: 10 * 1024 * 1024,
},
};

View File

@@ -123,4 +123,12 @@ export type Config = {
retentionReset: number;
};
};
attachmentSizeLimits: {
settingAttachmentSizeLimit: number;
userAvatarSizeLimit: number;
subscriberAvatarSizeLimit: number;
blockAttachmentSizeLimit: number;
contentAttachmentSizeLimit: number;
messageAttachmentSizeLimit: number;
};
};