Egg.js 实战:保存数据后异步获取阿里云 OSS 图片尺寸

2026-02-17 94 浏览 0 评论

在基于 Egg.js 开发的后端项目中,我们经常会遇到需要处理阿里云 OSS 存储图片的场景,比如在用户上传并保存图片数据后,自动获取图片的宽高和文件大小等信息。本文将详细讲解如何在 Egg.js 中实现“保存数据后异步获取阿里云 OSS 图片尺寸”的功能,帮助开发者高效处理 OSS 图片元信息。

一、功能背景与核心思路

在业务系统中,图片尺寸是常用的元数据(比如用于前端图片展示适配、后台数据统计等)。阿里云 OSS 提供了 image/info 处理接口,可以直接通过 URL 参数获取图片的宽高、文件大小等信息,无需下载图片到本地解析,既节省带宽又提升效率。

我们的核心实现思路是:

  1. 封装通用方法 getOssImageSize ,通过 OSS 的图片处理接口获取尺寸信息;
  2. 在数据保存成功后,通过 Egg.js 的 runInBackground 异步执行尺寸获取和更新操作,避免阻塞当前接口响应。

二、核心方法封装:getOssImageSize

首先封装一个通用的工具方法,专门用于从阿里云 OSS 获取图片的尺寸和文件大小信息。

2.1 方法完整代码

/**
 * @name getOssImageSize
 * @description 获取阿里云 oss 图片尺寸
 * @param {String} url 图片的 OSS 访问地址
 * @return {Object} 包含宽度、高度、文件大小的对象
 */
async getOssImageSize(url) {
  try {
    // 1. 拼接 OSS 图片信息查询参数,image/info 是 OSS 内置的图片信息处理接口
    const ossInfoUrl = `${url}?x-oss-process=image/info`;
    // 2. 通过 Egg.js 的 curl 方法发送 GET 请求,获取图片信息
    const res = await this.ctx.curl(ossInfoUrl, { 
      method: 'get', 
      dataType: 'json', // 指定返回数据格式为 JSON
      timeout: 5000 // 设置 5 秒超时,避免请求阻塞
    });

    // 3. 处理 OSS 返回的异常情况(比如图片不存在)
    if (res.data.detail === 'Not Found') {
      this.ctx.logger.warn(`OSS 图片不存在,URL:${url}`); // 记录警告日志
      return { width: 0, height: 0, size: 0 };
    }

    // 4. 解析并返回图片的宽、高、文件大小
    return {
      width: res.data.ImageWidth.value,
      height: res.data.ImageHeight.value,
      size: res.data.FileSize.value // 单位:字节
    };
  } catch (err) {
    // 5. 捕获请求过程中的异常(比如网络错误)
    this.ctx.logger.error('获取 OSS 图片尺寸失败:', err.message, '图片 URL:', url);
    return { width: 0, height: 0, size: 0 };
  }
},

2.2 代码逐段说明

  1. 参数与注释 :方法接收 url 参数(OSS 图片访问地址),通过 JSDoc 注释清晰说明方法功能、参数和返回值,提升代码可读性。
  2. OSS 接口拼接 :阿里云 OSS 的 image/info 处理接口可以直接通过 URL 参数调用,无需额外 SDK,只需在图片 URL 后拼接 ?x-oss-process=image/info 即可。
  3. CURL 请求配置 :使用 Egg.js 内置的 ctx.curl 发送请求,指定 dataType: 'json' 自动解析返回结果,同时设置 timeout 避免请求超时阻塞。
  4. 异常处理-图片不存在 :如果 OSS 返回 Not Found ,说明图片地址无效,返回默认值(宽高为 0)并记录警告日志。
  5. 正常解析返回值 :OSS 返回的 JSON 数据中, ImageWidth.valueImageHeight.valueFileSize.value 分别对应图片宽度、高度和文件大小,直接解析返回。
  6. 全局异常捕获 :通过 try/catch 捕获网络错误、请求超时等异常,记录错误日志并返回默认值,保证方法不会抛出异常导致业务中断。

三、异步执行:保存数据后更新图片尺寸

数据保存成功后,我们需要异步执行图片尺寸获取和更新操作,避免影响当前接口的响应速度(比如用户上传图片后,无需等待尺寸获取完成即可返回“保存成功”)。

3.1 核心代码实现

// 数据保存成功后执行(假设 body 是保存后的业务数据)
this.ctx.runInBackground(async () => {
  try {
    // 1. 调用封装的方法获取图片尺寸
    const { width, height } = await this.ctx.helper.getOssImageSize(body.image) || { width: 0, height: 0 };

    // 2. 仅当获取到有效宽高时,更新数据库
    if (width && height) {
      await this.ctx.service.mould.update(
        {
          image_width: width,
          image_height: height,
        },
        { id: body.id } // 更新条件:根据数据 ID 更新
      );
      this.ctx.logger.info(`成功更新图片尺寸,数据 ID:${body.id},宽:${width},高:${height}`);
    }
  } catch (err) {
    // 3. 捕获异步执行过程中的异常
    this.ctx.logger.error('异步更新图片尺寸失败:', err.message, '数据 ID:', body.id);
  }
});

3.2 关键逻辑说明

  1. 异步执行容器 :Egg.js 的 ctx.runInBackground 方法可以将任务放入后台异步执行,当前接口会立即返回,不会等待异步任务完成,极大提升接口响应速度。
  2. 调用尺寸获取方法 :通过 ctx.helper 调用上文封装的 getOssImageSize 方法(假设方法放在 Egg.js 的 helper 工具类中),并处理方法返回的默认值。
  3. 条件更新数据库 :仅当获取到有效宽高(width 和 height 不为 0)时,才调用 service 层的 update 方法更新数据库,避免无效更新。
  4. 异常捕获 :异步任务内部也需要捕获异常,避免未处理的错误导致进程退出,并通过日志记录错误详情,便于排查问题。

四、使用注意事项

  1. OSS 权限配置 :确保图片的 OSS 访问地址支持匿名访问,或配置了正确的访问权限,否则 image/info 接口会返回 403 错误。
  2. 日志规范 :通过 Egg.js 的 ctx.logger 记录日志(而非 console.log ),便于后续日志收集和分析。
  3. 超时控制 :必须为 curl 请求设置超时时间,避免因 OSS 服务异常导致请求长时间阻塞。
  4. 非图片文件处理 :如果 URL 对应的不是图片文件(比如文档、视频), image/info 接口会返回异常,建议在调用方法前增加文件类型校验。

总结

本文实现的 Egg.js 获取阿里云 OSS 图片尺寸功能,核心要点如下:

  1. 利用阿里云 OSS 的 image/info 内置接口,无需下载图片即可获取尺寸信息,高效且省带宽;
  2. 封装通用工具方法 getOssImageSize ,增加异常捕获和日志记录,保证方法健壮性;
  3. 使用 Egg.js 的 runInBackground 异步执行尺寸更新,避免阻塞接口响应,提升用户体验。

该方案适用于所有基于 Egg.js 的后端项目,可直接复用核心代码,只需根据自身业务调整数据库更新逻辑即可。


发布评论

发布评论前请先 登录
取消
0 评论
点赞
收藏

评论列表 0

暂无评论