Firebase Storage图片上传损坏问题排查求助
问题诊断与解决办法
核心问题:文件流未写完就触发上传
你的代码存在关键时序漏洞:busboy的close事件触发时,本地文件的写入流可能还未完全结束,就直接调用bucket.upload上传临时文件。摄像头拍摄的文件体积小,写入速度快,刚好能赶在上传前完成;但本地文件体积更大,写入未完成就上传,导致文件仅写入部分内容(即你看到的1.83kb空文件)。
代码修复方案
需要等待文件写入流完全结束后,再执行上传操作。通过监听写入流的finish事件来确保文件写入完成,同时调整代码逻辑顺序:
app.post("/createPost", (request, response) => { response.set("Access-Control-Allow-Origin", "*"); let token_id = uuidv4(); let fileData = null; let fields = {}; // 用Promise等待文件写入完成 const fileWritePromise = new Promise((resolve) => { const bb = busboy({ headers: request.headers }); bb.on("file", (name, file, info) => { const { filename, encoding, mimeType } = info; let filepath = path.join(os.tmpdir(), filename); const writeStream = fs.createWriteStream(filepath); file.pipe(writeStream); fileData = { filepath, mimeType }; console.log( `File [${name}]: filename: %j, encoding: %j, mimeType: %j`, filename, encoding, mimeType ); file .on("data", (data) => { console.log(`File [${name}] got ${data.length} bytes`); }) .on("close", () => { console.log(`File [${name}] done`); }); // 监听写入流完成事件,确认文件已完全写入 writeStream.on("finish", () => { console.log(`File ${filename} written to temp directory`); resolve(); }); }); bb.on("field", (name, val, info) => { console.log(`Field [${name}]: value: %j`, val); fields[name] = val; }); bb.on("close", () => { console.log("Done parsing form!"); }); request.pipe(bb); }); // 等待文件写入完成后执行上传 fileWritePromise.then(() => { bucket.upload( fileData.filepath, { uploadType: "media", metadata: { metadata: { contentType: fileData.mimeType, firebaseStorageDownloadTokens: token_id, }, }, }, (err, uploadedFile) => { if (err) { console.error("Upload failed:", err); response.status(500).send("Upload error"); return; } createDocument(uploadedFile); response.end(); } ); function createDocument(uploadedFile) { db.collection("posts") .doc(fields.id) .set({ id: fields.id, caption: fields.caption, location: fields.location, date: parseInt(fields.date), imgUrl: `https://firebasestorage.googleapis.com/v0/b/${bucket.name}/o/${uploadedFile.name}?alt=media&token=${token_id}`, name: fields.name, }) .then(() => { console.log("Post document created successfully"); }) .catch((docErr) => { console.error("Document creation failed:", docErr); }); } }).catch((writeErr) => { console.error("File write failed:", writeErr); response.status(500).send("File processing error"); }); });
额外排查说明
- Firebase Storage规则:你的规则完全开放,允许所有读写操作,因此不是规则导致的问题。
- 前端文件处理:你提到上传前图片已转为BLOB并正常显示,说明前端文件处理无问题,故障根源在后端写入与上传的时序逻辑。
内容的提问来源于stack exchange,提问作者Eric Andre
相关产品推荐
相关产品推荐

