前移上传模板可用性校验

This commit is contained in:
WuYongJie 2026-05-28 15:58:10 +08:00
parent 7157cd318a
commit 965871f8dc
3 changed files with 70 additions and 34 deletions

View File

@ -238,7 +238,15 @@ describe('素材模板字段链路测试', () => {
expect(response.status).toBe(400)
expect(data.errorCode).toBe('TEMPLATE_REQUIRED_FIELDS_MISSING')
expect(prisma.material.create).not.toHaveBeenCalled()
expect(validateTemplateId).not.toHaveBeenCalled()
expect(validateTemplateId).toHaveBeenCalledWith(
'template-1',
expect.objectContaining({
checkStatus: true,
logPerformance: true,
})
)
expect(uploadToS3).not.toHaveBeenCalled()
expect(uploadStreamToS3).not.toHaveBeenCalled()
})
test('上传成功时应写入 templateId 和自定义字段 metadata', async () => {
@ -273,6 +281,35 @@ describe('素材模板字段链路测试', () => {
expect(data.material.zipFileSize).toBe('0')
})
test('模板不可用时应在上传文件前拒绝', async () => {
const zipFile = createMockFile('inactive-template.zip', 'application/zip', 'zip-data')
validateTemplateId.mockResolvedValueOnce({
valid: false,
error: '模板已停用',
errorCode: 'TEMPLATE_INACTIVE',
templateStatus: 'inactive',
})
const response = await uploadMaterial(
buildUploadRequest({
zipFile,
templateFields: JSON.stringify({
productModel: '稳定材质',
customCode: 'CODE-INACTIVE',
}),
})
)
const data = await response.json()
expect(response.status).toBe(400)
expect(data.error).toBe('模板已停用')
expect(data.errorCode).toBe('TEMPLATE_INACTIVE')
expect(getTemplateWithFields).not.toHaveBeenCalled()
expect(uploadToS3).not.toHaveBeenCalled()
expect(uploadStreamToS3).not.toHaveBeenCalled()
expect(prisma.material.create).not.toHaveBeenCalled()
})
test('非音频原始素材上传应走流式上传,避免二次整文件 Buffer', async () => {
const zipFile = createMockFile('model.zip', 'application/zip', 'zip-data')

View File

@ -293,6 +293,36 @@ export async function POST(req: NextRequest) {
console.log('[Upload] User found:', user.username, 'Author name:', authorName)
if (templateId) {
console.log('[Upload] Validating template before file upload:', templateId)
const validation = await validateTemplateId(templateId, {
checkStatus: true,
logPerformance: true,
})
if (!validation.valid) {
console.error('[Upload] Template validation failed before file upload:', {
templateId,
error: validation.error,
errorCode: validation.errorCode,
validationTime: validation.validationTime,
})
return NextResponse.json(
{
error: validation.error || '模板验证失败',
errorCode: validation.errorCode,
},
{ status: 400 }
)
}
console.log('[Upload] Template validation passed before file upload:', {
templateId,
isBuiltin: validation.isBuiltin,
templateKey: validation.templateKey,
templateName: validation.templateName,
validationTime: validation.validationTime,
})
const templateFieldsValidation = await validateSubmittedTemplateFields({
templateId,
templateFields,
@ -634,39 +664,6 @@ export async function POST(req: NextRequest) {
))
}
// 验证模板ID(如果提供)
if (templateId) {
console.log('[Upload] Validating template:', templateId)
const validation = await validateTemplateId(templateId, {
checkStatus: true, // 检查模板状态
logPerformance: true, // 记录性能日志
})
if (!validation.valid) {
console.error('[Upload] Template validation failed:', {
templateId,
error: validation.error,
errorCode: validation.errorCode,
validationTime: validation.validationTime,
})
return await failWithCleanup(NextResponse.json(
{
error: validation.error || '模板验证失败',
errorCode: validation.errorCode,
},
{ status: 400 }
))
}
console.log('[Upload] Template validation passed:', {
templateId,
isBuiltin: validation.isBuiltin,
templateKey: validation.templateKey,
templateName: validation.templateName,
validationTime: validation.validationTime,
})
}
try {
const materialId = await generateMaterialId()
const material = await prisma.material.create({

View File

@ -529,11 +529,13 @@
- 已修复:上传链路现在通过 `uploadedArtifactUrls` 记录本次已经写入的对象。
- 已修复:`failWithCleanup()` 会在模板校验、数据库写入等失败路径调用 `cleanupUploadedArtifacts()`。
- 已修复:成功创建素材记录后会清空待清理列表,避免误删正常素材文件。
- 已修复:上传入口会在处理预览图、展示图和原始素材文件前先确认模板存在且启用。模板已停用或不存在时会直接拒绝,不再让客户等大文件上传完才失败,也不会写入对象存储。
- 仍需后续处理:上传过程仍有整文件进内存问题,归到 P1-11。
建议动作:
- 保持现有补偿清理测试覆盖。
- 保持“模板不可用时不上传文件”的测试覆盖,后续改上传方式时不能退回到文件写入后才校验模板。
- 后续如引入分片/直传上传,要继续保留“数据库失败自动清理已上传对象”的规则。
### P1-08 永久删除和清理失败时仍删除数据库记录(已完成第一轮修复)