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

如何编写自定义Mongoose插件实现S3对象返回签名URL?

解决Mongoose插件转换S3对象为签名URL的问题

核心思路

  1. 在插件初始化阶段遍历Schema,一次性收集所有标记了signurl: true的字段,避免每次查询重复遍历Schema
  2. 在find/findOne的post钩子中,对查询返回的单条或多条文档,针对收集到的字段生成S3签名URL并替换原字段值

完整插件实现

const { S3Client, GetObjectCommand } = require("@aws-sdk/client-s3");
const { getSignedUrl } = require("@aws-sdk/s3-request-presigner");

// 初始化S3客户端(建议通过环境变量配置密钥,避免硬编码)
const s3Client = new S3Client({
  region: process.env.AWS_REGION,
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
  }
});

const signURL = (schema) => {
  // 收集所有需要生成签名URL的字段路径
  const signableFields = [];
  schema.eachPath((path, schemaType) => {
    if (schemaType.options.signurl === true) {
      signableFields.push(path);
    }
  });

  // 处理find和findOne查询后的文档
  schema.post(['find', 'findOne'], async function(docs) {
    // 单文档处理逻辑
    const processSingleDoc = async (doc) => {
      for (const field of signableFields) {
        const s3Key = doc[field];
        if (!s3Key) continue;

        // 生成有效期1小时的S3签名URL
        const command = new GetObjectCommand({
          Bucket: process.env.AWS_S3_BUCKET,
          Key: s3Key
        });
        const signedUrl = await getSignedUrl(s3Client, command, { expiresIn: 3600 });
        
        doc[field] = signedUrl;
      }
    };

    // 区分数组(find返回)和单对象(findOne返回)处理
    if (Array.isArray(docs)) {
      await Promise.all(docs.map(processSingleDoc));
    } else if (docs) {
      await processSingleDoc(docs);
    }
  });
};

module.exports = signURL;

使用示例(与你的原代码兼容)

const userSchema = mongoose.Schema({
  profilePhoto: {
    type: String,
    signurl: true,
  },
  // 可扩展添加其他需要处理的字段
  coverImage: {
    type: String,
    signurl: true,
  }
});
userSchema.plugin(signURL);

关键细节说明

  • 用schema.eachPath遍历Schema字段是获取自定义signurl选项的正确方式,这一步在插件初始化时仅执行一次
  • post钩子中异步处理签名URL生成,注意用Promise.all批量处理数组文档提升效率
  • S3签名URL的有效期、存储桶等参数可根据业务需求调整

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 04:45:13