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