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

基于Moleculer Framework:MongoDB二进制文件下载API开发问题

问题分析与解决方案

现有代码的核心问题

  • 创建WriteStream后未执行写入操作,也未处理流的结束事件,导致文件无法保存
  • fs.write用法错误,正确方式应为fs.writeFile或通过流写入
  • Buffer.from(result.file.buffer, result.file.mimetype)逻辑错误:第二个参数应为编码格式(如base64)而非MIME类型,且result.file.buffer本身已是Buffer,无需二次转换
  • 未向客户端返回响应,前端无法触发下载
  • MongoDB连接关闭时机不合理,应确保操作完成后再关闭

解决方案

1. 实现客户端直接下载(API核心需求)

修改handler函数,通过设置响应头触发浏览器下载,同时确保数据库连接安全关闭:

async handler(ctx, res) {
    console.log("Came to main action handler-- DOWNLOAD");
    const fileId = ctx.params.id;
    console.log("Download step 1: " + fileId);
    let client;
    try {
        client = await MongoClient.connect(mongoURL);
        const db = client.db(dbName);
        const collection = db.collection(collectionName);
        const result = await collection.findOne({ _id: new ObjectId(fileId) });
        
        if (!result) {
            ctx.status = 404;
            ctx.body = "文件不存在";
            return;
        }

        const fileBuffer = result.file.buffer;
        const fileName = result.file.originalname;
        const mimeType = result.file.mimetype;

        // 设置响应头,强制浏览器触发下载
        ctx.set('Content-Type', mimeType);
        ctx.set('Content-Disposition', `attachment; filename="${encodeURIComponent(fileName)}"`);
        ctx.set('Content-Length', fileBuffer.length);
        
        // 将二进制数据返回给客户端
        ctx.body = fileBuffer;

        console.log(`文件 ${fileName} 已触发下载`);
    } catch (error) {
        console.log("错误: " + error);
        ctx.status = 500;
        ctx.body = "服务器内部错误";
    } finally {
        // 确保数据库连接无论结果如何都会关闭
        if (client) {
            await client.close();
        }
    }
},

2. 同时保存文件到服务器本地(可选需求)

如果需要将文件保存到服务器本地,修正流写入逻辑:

// 在获取到fileBuffer和fileName后添加以下代码
const savePath = `C:/upload/${fileName}`;
const writeStream = fs.createWriteStream(savePath);

// 写入Buffer并结束流
writeStream.write(fileBuffer);
writeStream.end();

// 监听流事件处理结果
writeStream.on('finish', () => {
    console.log(`文件已保存至 ${savePath}`);
});

writeStream.on('error', (err) => {
    console.error("保存文件失败:", err);
});

关键说明

  • 直接使用result.file.buffer即可,无需额外转换
  • encodeURIComponent用于处理文件名中的特殊字符,避免下载时出现乱码
  • finally块确保MongoDB连接资源被正确释放
  • 流操作需监听finish和error事件,处理保存成功或失败的情况

内容的提问来源于stack exchange,提问作者Lalith Rajendran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 22:15:14