Next.js中使用formidable遇API未返回响应问题求助
解决Next.js API路由
API resolved without sending a response问题 问题原因
你的async handler函数会在form.parse的回调执行前提前结束,Next.js检测到函数执行完毕但未在主执行流内返回响应(回调里的响应属于异步触发,不在handler的执行周期内),因此抛出该警告。即便前端能收到响应,Node.js的请求上下文已被提前标记为完成,导致警告出现。
修复方案:用Promise包裹异步操作
将回调式的form.parse和流式上传逻辑转为Promise,让async handler等待整个流程完成,确保响应在handler执行周期内发送。
修改后的完整代码:
export const config = { api: { bodyParser: false } } export default async function handler(req, res) { const { query: { uuid } } = req const token = await getToken({ req }) const key = JSON.parse(process.env.GOOGLE_APPLICATION_CREDENTIALS.toString()) if (!token) { return res.status(401).json({ error: '用户必须登录才能执行此操作' }) } const storage = new Storage({ projectId: process.env.PROJECT_ID, credentials: { client_email: key.client_email, private_key: key.private_key.replace(/\\n/g, '\n') } }) const form = formidable({ keepExtensions: true, }) try { // 包裹form.parse为Promise const [fields, files] = await new Promise((resolve, reject) => { form.parse(req, (err, fields, files) => err ? reject(err) : resolve([fields, files])) form.on('error', reject) }) const selectedFile = files.file[0]; if (!selectedFile) { console.error('未上传文件') return res.status(400).json({ error: '未上传文件' }) } const salt = crypto.randomBytes(16).toString('hex') const hashedFilename = crypto.createHash('sha256').update(selectedFile.originalFilename + salt).digest('hex') const bucket = storage.bucket(process.env.CLOUD_STORAGE_BUCKET_NAME) const blob = bucket.file(hashedFilename) // 包裹流式上传为Promise await new Promise((resolve, reject) => { const blobStream = createReadStream(selectedFile.filepath) .pipe(blob.createWriteStream({ resumable: false, contentType: selectedFile.mimetype })) blobStream.on('error', (err) => { console.error(`云存储上传出错: ${err}`) cleanupStreams(blobStream, selectedFile.filepath) reject(err) }) blobStream.on('finish', resolve) }) await blob.setMetadata({ metadata: { UUID: uuid, FILE_NAME: selectedFile.originalFilename, CREATION_DATE: getDate(), } }) cleanupStreams(blobStream, selectedFile.filepath) return res.status(201).json({ message: `文件上传成功: ${selectedFile.newFilename}` }) } catch (err) { console.error(`请求处理出错: ${err}`) // 避免重复发送响应 if (!res.headersSent) { const statusCode = err.message.includes('No file uploaded') ? 400 : 500 const errorMsg = err.message || '服务器内部错误' return res.status(statusCode).json({ error: errorMsg }) } } }
核心调整说明
- Promise化异步操作:将
form.parse和流式上传的回调逻辑转为Promise,用await等待所有异步步骤完成,确保handler不会提前退出。 - 统一错误处理:通过try/catch捕获所有异常,确保错误场景下也能返回合法响应,同时检查
res.headersSent避免重复发送响应。 - 同步执行流:让整个上传流程处于handler的主执行流中,符合Next.js对API路由的响应要求。
内容的提问来源于stack exchange,提问作者Lofton Gentry
相关产品推荐
相关产品推荐

