Egg.js 实战:保存数据后异步获取阿里云 OSS 图片尺寸
在基于 Egg.js 开发的后端项目中,我们经常会遇到需要处理阿里云 OSS 存储图片的场景,比如在用户上传并保存图片数据后,自动获取图片的宽高和文件大小等信息。本文将详细讲解如何在 Egg.js 中实现“保存数据后异步获取阿里云 OSS 图片尺寸”的功能,帮助开发者高效处理 OSS 图片元信息。
一、功能背景与核心思路
在业务系统中,图片尺寸是常用的元数据(比如用于前端图片展示适配、后台数据统计等)。阿里云 OSS 提供了 image/info 处理接口,可以直接通过 URL 参数获取图片的宽高、文件大小等信息,无需下载图片到本地解析,既节省带宽又提升效率。
我们的核心实现思路是:
- 封装通用方法
getOssImageSize,通过 OSS 的图片处理接口获取尺寸信息; - 在数据保存成功后,通过 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 代码逐段说明
- 参数与注释 :方法接收
url参数(OSS 图片访问地址),通过 JSDoc 注释清晰说明方法功能、参数和返回值,提升代码可读性。 - OSS 接口拼接 :阿里云 OSS 的
image/info处理接口可以直接通过 URL 参数调用,无需额外 SDK,只需在图片 URL 后拼接?x-oss-process=image/info即可。 - CURL 请求配置 :使用 Egg.js 内置的
ctx.curl发送请求,指定dataType: 'json'自动解析返回结果,同时设置timeout避免请求超时阻塞。 - 异常处理-图片不存在 :如果 OSS 返回
Not Found,说明图片地址无效,返回默认值(宽高为 0)并记录警告日志。 - 正常解析返回值 :OSS 返回的 JSON 数据中,
ImageWidth.value、ImageHeight.value、FileSize.value分别对应图片宽度、高度和文件大小,直接解析返回。 - 全局异常捕获 :通过
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 关键逻辑说明
- 异步执行容器 :Egg.js 的
ctx.runInBackground方法可以将任务放入后台异步执行,当前接口会立即返回,不会等待异步任务完成,极大提升接口响应速度。 - 调用尺寸获取方法 :通过
ctx.helper调用上文封装的getOssImageSize方法(假设方法放在 Egg.js 的 helper 工具类中),并处理方法返回的默认值。 - 条件更新数据库 :仅当获取到有效宽高(width 和 height 不为 0)时,才调用 service 层的
update方法更新数据库,避免无效更新。 - 异常捕获 :异步任务内部也需要捕获异常,避免未处理的错误导致进程退出,并通过日志记录错误详情,便于排查问题。
四、使用注意事项
- OSS 权限配置 :确保图片的 OSS 访问地址支持匿名访问,或配置了正确的访问权限,否则
image/info接口会返回 403 错误。 - 日志规范 :通过 Egg.js 的
ctx.logger记录日志(而非console.log),便于后续日志收集和分析。 - 超时控制 :必须为 curl 请求设置超时时间,避免因 OSS 服务异常导致请求长时间阻塞。
- 非图片文件处理 :如果 URL 对应的不是图片文件(比如文档、视频),
image/info接口会返回异常,建议在调用方法前增加文件类型校验。
总结
本文实现的 Egg.js 获取阿里云 OSS 图片尺寸功能,核心要点如下:
- 利用阿里云 OSS 的
image/info内置接口,无需下载图片即可获取尺寸信息,高效且省带宽; - 封装通用工具方法
getOssImageSize,增加异常捕获和日志记录,保证方法健壮性; - 使用 Egg.js 的
runInBackground异步执行尺寸更新,避免阻塞接口响应,提升用户体验。
该方案适用于所有基于 Egg.js 的后端项目,可直接复用核心代码,只需根据自身业务调整数据库更新逻辑即可。




