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

如何查看MongoDB中存储的超过1MB的Base64格式PDF文件

问题根因

  1. 主流浏览器对Data URL的长度限制为2~5MB,超过该长度的资源会被直接拦截,无法通过embed标签加载
  2. 将大体积PDF的Base64编码直接嵌入EJS页面,会导致HTML体积骤增、渲染阻塞,embed标签无法正常解析大段Base64内容
  3. 当前采用的Mongoose Buffer类型存储依赖MongoDB单BSON文档存储,单文档最大上限为16MB,后续文件体积继续增长仍会遇到瓶颈

临时修复方案(无需改造现有存储逻辑)

不需要修改现有存储逻辑,仅新增文件流接口,直接返回二进制PDF内容,避免将Base64嵌入页面:

1. 新增文件读取接口

在app.js中添加如下代码:

app.get('/file/:id', async (req, res) => {
  try {
    const file = await File.findById(req.params.id);
    if (!file) return res.status(404).send('文件不存在');
    res.setHeader('Content-Type', file.fileType);
    // 如需默认下载而非嵌入,可添加以下响应头
    // res.setHeader('Content-Disposition', `attachment; filename="${file.fileName}"`);
    res.send(file.file);
  } catch (err) {
    console.log(err);
    res.status(500).send('文件读取失败');
  }
});

2. 修改EJS渲染逻辑

将layout.ejs中的embed标签替换为接口地址引用,无需再使用虚拟属性生成的Data URL:

<% if(files) { %>
  <% files.forEach(m => { %>
    <embed type="application/pdf" src="/file/<%= m._id %>" width="300" height="300">
    <!-- 可按需添加下载链接 -->
    <a href="/file/<%= m._id %>" download="<%= m.fileName %>">下载PDF</a>
  <% }) %>
<% } %>

3. 调整bodyParser限制

将app.js中bodyParser的limit调整为你需要的最大文件大小(最大不超过16MB即可):

app.use(bodyParser.json({limit: "15mb"}));
app.use(bodyParser.urlencoded({limit: "15mb",extended: true,parameterLimit: 5000}));

生产级方案(GridFS改造,支持任意大小PDF)

GridFS会将大文件拆分为256KB的块存储,不受单文档16MB限制,是MongoDB存储大文件的标准方案,完整实现如下:

1. 安装依赖

npm install multer gridfs-stream

2. 初始化GridFS实例

在app.js的数据库连接成功回调中添加GridFS初始化逻辑:

const Grid = require('gridfs-stream');
const multer = require('multer');
let gfs;

db.on("open", ()=>{
  console.log("database connection success");
  // 初始化GridFS实例
  gfs = Grid(db.db, mongoose.mongo);
  gfs.collection('pdfFiles'); // 自定义存储集合名
});

// 配置文件上传中间件
const storage = multer.memoryStorage();
const upload = multer({
  storage: storage,
  fileFilter: (req, file, cb) => {
    if (file.mimetype === 'application/pdf') {
      cb(null, true);
    } else {
      cb(new Error('仅支持上传PDF格式文件'), false);
    }
  }
});

3. 改造上传接口

app.post("/add", upload.single('fileUpload'), async (req,res)=>{
  const fileName = req.body.fileName;
  const { buffer, mimetype } = req.file;
  // 将文件写入GridFS
  const writeStream = gfs.createWriteStream({
    filename: fileName,
    content_type: mimetype,
    bucketName: 'pdfFiles' // 和初始化时的集合名保持一致
  });
  writeStream.write(buffer);
  writeStream.end();
  
  writeStream.on('close', () => res.redirect('/'));
  writeStream.on('error', (err) => {
    console.log(err);
    res.status(500).send('文件上传失败');
  });
});

4. 新增GridFS文件读取接口

app.get('/file/:filename', (req, res) => {
  gfs.files.findOne({ filename: req.params.filename }, (err, file) => {
    if (!file || file.length === 0) return res.status(404).send('文件不存在');
    if (file.contentType !== 'application/pdf') return res.status(400).send('非PDF文件');
    // 流式返回文件内容
    const readStream = gfs.createReadStream(file.filename, { bucketName: 'pdfFiles' });
    res.setHeader('Content-Type', file.contentType);
    readStream.pipe(res);
  });
});

5. 改造首页文件列表查询逻辑

将首页查询逻辑改为从GridFS的files集合中读取文件列表即可:

app.get("/",async(req,res,next)=>{
  try{
    gfs.files.find().toArray((err, files) => {
      res.render("layout", { files });
    });
  }catch (err){
    console.log("err: "+ err);
  }
});

EJS的渲染逻辑和临时方案保持一致即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 05:45:02