function registerRemixAssetUploadRoutes(app, deps) { const { path, assetUpload, qiniuUploadUrl, qiniuCdnDomain, buildDigitalHumanAssetKey, buildQiniuUploadToken, } = deps; app.post('/api/remix/upload-asset', assetUpload.single('file'), async (req, res) => { try { if (!req.file) { return res.status(400).json({ error: '未收到素材文件' }); } const mimeType = req.file.mimetype || 'application/octet-stream'; const kind = mimeType.startsWith('audio/') ? 'audio' : mimeType.startsWith('video/') ? 'video' : 'image'; const key = buildDigitalHumanAssetKey(req.file.originalname, kind); const token = buildQiniuUploadToken(key); const formData = new FormData(); formData.append('token', token); formData.append('key', key); formData.append('file', new Blob([req.file.buffer], { type: mimeType }), path.basename(key)); const response = await fetch(qiniuUploadUrl, { method: 'POST', body: formData, }); const text = await response.text(); let payload = null; try { payload = text ? JSON.parse(text) : null; } catch { payload = null; } if (!response.ok) { return res.status(response.status).json({ error: payload?.error || payload?.message || text || '七牛素材上传失败', detail: payload || text || '', }); } const uploadedKey = payload?.key || key; const url = `${qiniuCdnDomain.replace(/\/$/, '')}/${uploadedKey}`; if (!uploadedKey || !url) { return res.status(500).json({ error: '七牛未返回素材 Key', detail: payload || text || '' }); } res.json({ success: true, url, key: uploadedKey, mimeType, kind, }); } catch (error) { console.error('❌ 上传重塑素材失败:', error); res.status(500).json({ error: `上传重塑素材失败: ${error.message}` }); } }); } module.exports = { registerRemixAssetUploadRoutes };