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

如何将文件上传至MongoDB或Mongoose并获取对应存储访问URL路径

实现Mongoose文件上传及访问URL生成方案

以下是实现pdf、文本等格式文件上传到Mongoose并生成可访问URL路径的完整方案:

方案选型

根据文件大小可以选择两种实现思路:

  • 小于16MB的小文件:直接将文件二进制内容存入Mongoose字段,实现逻辑最简单
  • 大于16MB的大文件:使用MongoDB原生GridFS分块存储,适配大文件存储要求

小文件上传实现(小于16MB)

1. 定义Mongoose存储Schema

const mongoose = require('mongoose');

const fileSchema = new mongoose.Schema({
  fileName: { type: String, required: true },
  fileType: { type: String, required: true },
  // 存储文件二进制内容
  fileData: { type: Buffer, required: true },
  uploadTime: { type: Date, default: Date.now }
});

const FileModel = mongoose.model('File', fileSchema);

2. 实现上传接口

使用multer中间件读取上传的文件内容,无需本地落盘直接存入数据库:

const multer = require('multer');
// 配置内存存储
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });

app.post('/upload', upload.single('file'), async (req, res) => {
  try {
    const newFile = new FileModel({
      fileName: req.file.originalname,
      fileType: req.file.mimetype,
      fileData: req.file.buffer
    });
    await newFile.save();
    // 生成可访问的URL路径,用文档_id作为唯一标识
    const accessUrl = `${req.protocol}://${req.get('host')}/file/${newFile._id}`;
    res.json({ code: 0, url: accessUrl });
  } catch (err) {
    res.status(500).json({ code: 1, msg: '上传失败' });
  }
});

3. 实现文件访问接口

匹配生成的URL规则,从数据库读取文件内容返回给前端:

app.get('/file/:id', async (req, res) => {
  try {
    const file = await FileModel.findById(req.params.id);
    if (!file) return res.status(404).send('文件不存在');
    // 设置响应头,支持直接在浏览器展示文件
    res.set({
      'Content-Type': file.fileType,
      'Content-Disposition': `inline; filename="${file.fileName}"`
    });
    res.send(file.fileData);
  } catch (err) {
    res.status(500).send('文件读取失败');
  }
});

大文件上传实现(大于16MB)

超过MongoDB单文档16MB大小限制的文件,使用GridFS分块存储实现:

const { GridFSBucket } = require('mongodb');
// 初始化GridFS存储桶
let gfs;
mongoose.connection.once('open', () => {
  gfs = new GridFSBucket(mongoose.connection.db, { bucketName: 'largeFiles' });
});

// 大文件上传接口
app.post('/upload-large', upload.single('file'), (req, res) => {
  const writeStream = gfs.openUploadStream(req.file.originalname, {
    contentType: req.file.mimetype
  });
  writeStream.end(req.file.buffer);
  writeStream.on('finish', () => {
    const accessUrl = `${req.protocol}://${req.get('host')}/file-large/${writeStream.id}`;
    res.json({ code: 0, url: accessUrl });
  });
});

// 大文件访问接口
app.get('/file-large/:id', (req, res) => {
  try {
    const readStream = gfs.openDownloadStream(new mongoose.Types.ObjectId(req.params.id));
    readStream.on('error', () => res.status(404).send('文件不存在'));
    readStream.pipe(res);
  } catch (err) {
    res.status(500).send('文件读取失败');
  }
});

注意事项

  • 生产环境建议给文件访问接口增加权限校验,避免未授权访问
  • 高频访问的文件不建议长期存在数据库,更推荐搭配对象存储服务使用,数据库仅存储文件URL
  • 上传前建议增加文件类型、大小校验,避免非法文件入库

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 00:15:08