v4.0.15上传图片自动压缩

This commit is contained in:
developer_liu
2026-09-03 16:04:10 +08:00
parent b60b16a84f
commit c26ebdde1b
9 changed files with 308 additions and 13 deletions
@@ -3,6 +3,7 @@ import type { ResourceBizType, ResourceMediaType, ResourceOwnerType } from '@pri
import { Prisma } from '@prisma/client';
import { PrismaService } from '../../common/prisma/prisma.module';
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
import { prepareActivityPosterUpload } from '../../common/image/activity-poster-upload.util';
import { OSS_PROVIDER } from '../../integrations/integrations.constants';
import type { IOssProvider } from '../../integrations/oss/oss.interface';
import { logOssUpload, type OssActorRef } from '../../integrations/oss/oss-log.util';
@@ -105,19 +106,75 @@ export class ResourceService {
if (dto.bizType === 'AVATAR' && !file.mimetype?.startsWith('image/')) {
throw new BadRequestException('头像仅支持图片文件');
}
if (dto.bizType === 'ACTIVITY_POSTER' && dto.mediaType === 'IMAGE' && !file.mimetype?.startsWith('image/')) {
throw new BadRequestException('活动图仅支持图片文件');
}
let uploadBuffer = file.buffer;
let uploadMimeType = file.mimetype;
let imageMeta: {
width: number;
height: number;
originalWidth: number;
originalHeight: number;
compressed: boolean;
fileSize: number;
} | undefined;
if (dto.bizType === 'ACTIVITY_POSTER' && dto.mediaType === 'IMAGE') {
const prepared = await prepareActivityPosterUpload({
buffer: file.buffer,
mimeType: file.mimetype,
});
if (prepared.buffer.length > maxUploadBytes) {
const message = `活动图压缩后仍超过 ${Math.floor(maxUploadBytes / 1024 / 1024)}MB(当前 ${prepared.width}×${prepared.height}`;
await logOssUpload(this.prisma, {
scene: 'UPLOAD_PUT_OBJECT',
actorRef: actor,
requestBody: {
...requestBody,
imageWidth: prepared.width,
imageHeight: prepared.height,
compressed: prepared.compressed,
},
status: 'FAILED',
errorMessage: message,
});
throw new BadRequestException(message);
}
uploadBuffer = prepared.buffer;
uploadMimeType = prepared.mimeType;
imageMeta = {
width: prepared.width,
height: prepared.height,
originalWidth: prepared.originalWidth,
originalHeight: prepared.originalHeight,
compressed: prepared.compressed,
fileSize: prepared.buffer.length,
};
}
try {
const result = await this.oss.putObject({
bizType: dto.bizType,
mediaType: dto.mediaType,
fileName: file.originalname || 'upload.bin',
buffer: file.buffer,
mimeType: file.mimetype,
buffer: uploadBuffer,
mimeType: uploadMimeType,
});
await logOssUpload(this.prisma, {
scene: 'UPLOAD_PUT_OBJECT',
actorRef: actor,
requestBody,
requestBody: {
...requestBody,
...(imageMeta
? {
imageWidth: imageMeta.width,
imageHeight: imageMeta.height,
compressed: imageMeta.compressed,
}
: {}),
},
responseBody: {
bucket: result.bucket,
region: result.region,
@@ -139,14 +196,14 @@ export class ResourceService {
ossKey: result.ossKey,
url: result.url,
fileName: file.originalname || 'avatar',
fileSize: BigInt(file.size),
mimeType: file.mimetype,
fileSize: BigInt(uploadBuffer.length),
mimeType: uploadMimeType,
status: 'ACTIVE',
},
});
return serializeBigInt({ ...result, resourceId: resource.id });
return serializeBigInt({ ...result, resourceId: resource.id, ...(imageMeta ? { image: imageMeta } : {}) });
}
return result;
return { ...result, ...(imageMeta ? { image: imageMeta } : {}) };
} catch (err) {
await logOssUpload(this.prisma, {
scene: 'UPLOAD_PUT_OBJECT',