You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 16:25:30