BackBlaze B2 Cloud Storage大文件上传请求无限挂起问题求助
NextJS + BackBlaze B2 大文件上传挂起问题排查
我开发了一个NextJS应用,采用BackBlaze B2 Cloud Storage存储用户上传的视频与图片。当前遇到异常问题:图片上传始终成功,但视频上传时,1-2MB的小视频可正常上传,一旦视频超过2MB,请求便无限挂起且无任何错误抛出;该问题存在不一致性,曾成功上传过一次4MB视频,但后续尝试均失败。项目使用backblaze-b2库,以下是相关代码,恳请提供排查思路。
前端组件调用方法(类内)
static async uploadContent(file: File, storeContentInfo: Function) { try { const arrayBuffer = await new Promise<ArrayBuffer>((resolve, reject) => { const reader = new FileReader(); reader.readAsArrayBuffer(file); reader.onload = () => resolve(reader.result as ArrayBuffer); reader.onerror = reject; }); const base64String = Buffer.from(arrayBuffer).toString('base64'); if (!base64String) { throw new Error('Failed to read file content'); } const contentId = BackBlazeHelpers.generateUniqueId(); const contentInfo = { fileName: file.name, fileType: file.type, fileContent: base64String, contentId, contentInfo: { size: file.size, }, }; console.log('CLIENT SIDE: RIGHT BEFORE API CALL'); // STORE FILE IN BACKBLAZE const response = await axiosInstance.post('/api/upload-content', contentInfo); // STORE FILE INFO IN FIREBASE storeContentInfo(contentId, response.data.fileUrl, file.type, file.size); console.log('Upload successful', response.data.fileUrl); } catch (error) { console.error('Error uploading content', error.message); throw error; } }
后端API通信方法
export const config = { api: { bodyParser: { sizeLimit: '50mb', }, }, }; const uploadContent = async (req: NextApiRequest, res: NextApiResponse) => { if (req.method !== 'POST') { return res.status(405).end(); } const { fileName, fileType, fileContent, contentId, contentInf } = req.body; try { const b2 = new B2({ applicationKey: B2_APPLICATION_KEY, applicationKeyId: B2_KEY_ID, }); // GET AUTHORIZATION await b2.authorize(); // GET UPLOAD URL const uploadUrlResponse = await b2.getUploadUrl({ bucketId: BUCKET_ID, }); const { uploadUrl, authorizationToken } = uploadUrlResponse.data; // UPLOAD THE FILE await b2.uploadFile({ uploadUrl, uploadAuthToken: authorizationToken, fileName: encodeURIComponent(fileName), mime: fileType, data: Buffer.from(fileContent, 'base64'), hash: 'do_not_verify', }); // URL THAT LEADS TO THE FILE THAT WAS UPLOADED const fileUrl = `https://f003.backblazeb2.com/file/${BUCKET_NAME}/${encodeURIComponent(fileName)}`; return res.status(200).json({ message: 'Upload successful', fileUrl }); } catch (error) { console.error(error.message); return res.status(500).json({ error: 'Error uploading content' }); } };
排查思路
- 前端Base64转换的性能与体积问题:大文件转Base64会额外增加约33%的数据体积,2MB视频转完后体积超过2.6MB,更大的文件会导致前端内存占用飙升,甚至请求发送超时。建议改用
FormData直接传输文件,完全避免Base64转换,大幅减少数据量和内存消耗。 - Next.js API路由超时限制:虽然配置了
bodyParser.sizeLimit,但Next.js API路由默认存在超时限制(如Vercel部署环境为10秒),大文件上传耗时若超过该阈值,请求会被静默挂起。可尝试在API路由配置中增加超时参数,或改用流式上传方式处理大文件。 - BackBlaze B2上传机制限制:当前采用单文件上传,大文件上传时易受网络波动影响,导致连接中断但未触发错误捕获。建议改用BackBlaze B2的分片上传机制(即使文件小于100MB也可使用),同时检查backblaze-b2库版本,确认是否存在已知的大文件上传bug。
- 错误捕获与日志缺失:后端仅捕获顶层错误,
b2.uploadFile内部可能存在未被捕获的Promise拒绝,或网络层错误(如TCP连接断开)未被正确处理。建议为每一步异步操作添加单独的try/catch,并在Chrome DevTools的Network面板查看请求的实际状态,同时在后端添加更详细的日志(如上传进度、请求耗时)。 - 文件名编码与重复实例化问题:当前用
encodeURIComponent处理文件名,特殊字符可能导致BackBlaze B2处理异常;另外每次上传都重新实例化B2并授权,会增加额外延迟甚至并发冲突。建议生成唯一文件名避免特殊字符干扰,同时缓存B2实例与授权信息,减少重复操作。
内容的提问来源于stack exchange,提问作者stefanomusicman
相关产品推荐
相关产品推荐

