如何在LoopBack 4中实现文件上传至MongoDB GridFS?
LoopBack 4 对接MongoDB GridFS 文件上传实现修正方案
现有代码问题梳理
- 重复创建MongoDB连接:代码中同时通过
mongoose.createConnection和GridFsStorage构造参数传入MongoURL,会生成两条独立的数据库连接,造成不必要的资源占用 - 存在无效代码:声明的
gfs变量及对应的连接监听逻辑全程未被使用,storage;单句无任何执行意义,均可直接删除 - GridFS桶名配置不一致:临时定义的gfs对象设置的集合名为
uploads,但GridFsStorage配置的bucketName为自定义字符串,后续读取文件时会出现找不到对应存储桶的问题 - 文件大小取值时机错误:multer触发
file回调时还未完成全文件解析,此时从file对象中读取的size字段为undefined,无法正确存储 - 未做异常兜底:MongoURL拼接、crypto生成随机文件名阶段没有异常捕获逻辑,极端情况会导致服务报错
修正后的完整代码
import * as multer from 'multer'; import * as mongoose from 'mongoose'; import { GridFsStorage } from 'multer-gridfs-storage'; import * as crypto from 'crypto'; import * as path from 'path'; // 注意替换为你自己项目的MongoDataSource路径 import { MongoDataSource } from '../datasources'; protected configureFileUpload(destination?: string) { // 拼接MongoDB连接URL const mongoConfig = MongoDataSource.defaultConfig; const url = `mongodb://${mongoConfig.user}:${mongoConfig.password}@${mongoConfig.host}:${mongoConfig.port}/${mongoConfig.database}`; // 初始化GridFS存储 const storage = new GridFsStorage({ url: url, file: (req: any, file: any) => { return new Promise((resolve, reject) => { // 生成16位随机文件名避免重复 crypto.randomBytes(16, (err, buf) => { if (err) return reject(err); const filename = buf.toString('hex') + path.extname(file.originalname); const fileInfo = { filename: filename, bucketName: 'uploads', // 统一存储桶名 metadata: { originalName: file.originalname, encoding: file.encoding, mimetype: file.mimetype, expires: Date.now() + 1000 * 60 * 60 // 1小时后过期,无需过期可删除该字段 } }; resolve(fileInfo); }); }); } }); // 允许接收任意名称的上传文件 return multer({ storage: storage }).any(); }
LoopBack 4 接口集成步骤
- 提前安装所有依赖:执行
npm i multer mongoose multer-gridfs-storage @types/multer crypto path完成依赖安装 - 将上述方法放到你的上传业务对应的Controller类中
- 编写上传接口,在接口逻辑中调用
configureFileUpload方法解析上传的文件流,解析完成后可从request.files中获取存储到GridFS后的文件ID、文件名等信息返回给前端 - 若需要存储文件大小,可在文件上传完成后,从返回的文件信息中获取size字段,调用GridFS的update方法更新对应文件的metadata即可
常见问题排查
- 若MongoDB未开启身份认证,拼接URL时需要去掉用户名和密码的部分,避免连接URL格式错误
- 跨域请求无法上传的情况,需要在LoopBack4的CORS配置中允许对应域名的请求
- 文件读取报错时,优先检查存储桶名是否和上传时配置的
uploads一致
内容的提问来源于stack exchange,提问作者Samson Ayalew
相关产品推荐
相关产品推荐

