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

多文件上传Backblaze:代码未等待Promise完成就执行next的问题

解决Backblaze上传完成前调用next()的问题

你的核心问题是异步操作未被正确等待,导致next()在文件上传完成前就被调用。以下是问题拆解和修复后的代码:

问题根源

  • 混用then链与async/await,两种异步处理方式嵌套导致执行顺序混乱
  • fs.readdir采用回调写法,内部的上传循环不会被外部的then等待
  • 第二个then会直接跳过上传流程执行,此时imageIds还没收集到文件ID

修复方案

改用Promise风格的文件操作,全程用async/await确保所有异步操作完成后再执行next():

import fs from "fs/promises"; // 改用promise版fs
import B2 from "backblaze-b2";
import path from "path";
import dotenv from "dotenv";

dotenv.config();

export const uploadToBackBlaze = async (req, res, next) => {
    console.log("I'm here uploading to Backblaze");

    const b2 = new B2({
        applicationKeyId: process.env.BACKBLAZE_ACCOUNT_ID,
        applicationKey: process.env.BACKBLAZE_MASTER_APPLICATION_ID,
    });

    const __dirname = path.resolve();
    const tempDir = path.join(__dirname, "chapterTemp");
    const imageIds = [];

    try {
        // 用await替代then,等待授权完成
        await b2.authorize();
        const bucketId = process.env.BACKBLAZE_BUCKET_ID;

        // 用promise版readdir,等待文件列表读取完成
        const files = await fs.readdir(tempDir);
        
        // 遍历文件,逐个等待上传完成
        for (const file of files) {
            const filePath = path.join(tempDir, file);
            // 用promise版readFile替代同步读取,避免阻塞事件循环
            const fileData = await fs.readFile(filePath);
            const uploadFileName = file; // path.join(file)没必要,直接用文件名即可
            
            const uploadUrl = await b2.getUploadUrl(bucketId);
            const response = await b2.uploadFile({
                uploadUrl: uploadUrl.data.uploadUrl,
                uploadAuthToken: uploadUrl.data.authorizationToken,
                filename: uploadFileName,
                data: fileData,
                // 修复mime判断:原写法逻辑错误,会一直返回"image/png"
                mime: filePath.match(/\.(png|jpg|jpeg|webp)$/i)?.[0].slice(1).replace('jpg', 'jpeg') || "application/octet-stream"
            });
            
            console.log(response.data.fileId);
            imageIds.push(response.data.fileId);
        }

        // 所有上传完成后再执行后续逻辑
        console.log(imageIds);
        req.imageIds = imageIds;
        next();
    } catch (error) {
        console.error(error);
        return res.status(500).json({ message: error.message });
    }
};

额外优化点

  • 替换同步的fs.readFileSync为异步的fs.readFile,避免阻塞Node.js事件循环
  • 修复了mime字段的逻辑错误:原写法中"image/png" || "image/jpg"...会始终返回第一个值,现在根据文件后缀动态判断
  • 移除不必要的path.join(file),直接使用文件名作为上传文件名

内容的提问来源于stack exchange,提问作者Shilajit Dutta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:42:53