写点什么

Nest 实现 OSS 签名直传上传回调

作者:昆吾kw
  • 2023-06-19
    天津
  • 本文字数:2055 字

    阅读完需:约 7 分钟

回顾

前文《Nestjs+Vue 实现阿里云 OSS 服务端签名直传》详细介绍了如何在 Nest 服务端基于 Post Policy 生成临时签名,响应给客户端,再由客户端实现文件直传 OSS 的过程。


这种方案的优点是能减轻应用服务器的压力,节省流量,最重要是安全。但是在客户端将文件上传到 OSS 的结果如何,文件存储的地址,文件大小等信息,客户端和服务端都全然不知。


所以在前面的基础上,可以再加上一个步骤,设置上传回调,这样 OSS 完成文件存储后,可以将相关信息响应给服务端,服务端将处理结果再响应给 OSS ,再由 OSS 将信息响应给客户端。整个流程如下:


准备

需要准备一个域名和一台有公网 IP 的服务器,将域名解析到服务器上,在服务器中运行 Nest 程序,用来和 OSS 服务通信。

存储桶的跨域设置

前文中将允许的来源设置为了 *,现在改为真实的域名。


在存储桶中选择“数据安全” - “跨域设置”,编辑跨域规则:


Nest 服务端

使用前文示例的代码,只需要做一些小小的改动即可。

添加路由方法

oss.controller.ts 中新增一个控制器方法,用来处理 OSS 发来的回调请求。从请求头中解析出 x-oss-pub-key-url ,用来判断请求来源,并且从请求体中解析出文件信息。


import { Controller, Get, Post } from '@nestjs/common';import { OssService } from './oss.service';@Controller('oss')export class OssController {  constructor(private oss: OssService) {}      // 接收 OSS 回调  @Post('result')  getResult(@Headers('x-oss-pub-key-url') xOssPubKeyUrl: string,  @Body() file: any) {    return this.oss.getResult(xOssPubKeyUrl, file);  }}
复制代码

添加服务方法

oss.service.ts 先修改原来的 getSignature 方法,生成签名等信息后,还要设置回调请求需要的参数:


async getSignature() {    const config = {      // ...      // 设置上传回调URL,即回调服务器地址,用于处理应用服务器与 OSS 之间的通信      // OSS 会在文件上传完成后,把文件信息通过此回调URL发送给应用服务器      callbackUrl: 'http://kunwu.tech:3000/oss/result',    };
// 上传回调。 const callback = { // 设置回调请求的服务器地址 callbackUrl: config.callbackUrl, // 设置回调的内容,${object} 等占位符会由 OSS 进行填充 // ${object}表示文件的存储路径,${mimeType}表示资源类型,对于图片类型的文件,可以通过${imageInfo.height}等去设置宽高信息 callbackBody: 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}', // 设置回调的内容类型,也支持 application/json callbackBodyType: 'application/x-www-form-urlencoded', };
// 响应给客户端的签名和策略等信息 return { // ... // 传给客户端的回调参数,需要通过Buffer.from 对 JSON 进行 Base64 编码 callback: Buffer.from(JSON.stringify(callback)).toString('base64'),};
复制代码


还需要再增加一个方法,来处理 OSS 发来的请求。它接收控制器传递的两个参数,判断请求来源是 OSS 服务器之后,就可以将文件信息响应给客户端:


async getResult(xOssPubKeyUrl: string, file: any) {    // 通过 Base64 解码公钥地址    const pubKeyAddr = Buffer.from(xOssPubKeyUrl, 'base64').toString('ascii');
// 判断请求头中的 x-oss-pub-key-url 是否来源于OSS服务器 if (!pubKeyAddr.startsWith('https://gosspublic.alicdn.com/')) { // 如果不是来源于OSS服务器,则返回 “verify not ok”,表明回调失败 return { status: 'verify not ok', }; } // 如果 x-oss-pub-key-url 来源于OSS服务器,则返回“Ok”和文件信息,表明回调成功 return { status: 'Ok', file, };}
复制代码

前端

在前面的基础之上,现在向服务器请求签名信息返回的结果中会包含一条 callback



向 OSS 上传文件时,需要将 callback 也携带上:


// 使用Policy和签名上传图片到 OSSconst handleUpload = async () => {  // .....  const ossData = await getOssData()
// ..... // 设置回调信息 formdata.append('callback', ossData.callback) }
复制代码


在浏览器中选择一个文件上传到 OSS,查看下响应信息:



可以看到,这个信息就是我们在服务端设置的 /oss/result 接口的返回的数据:


return { status: 'Ok', file,};
复制代码

总结

代码已上传,点击这里查看


本文在上篇文章的基础上,增加了设置回调请求的步骤,这样就形成了一个完整的闭环:


  1. 客户端上传文件前,先请求临时签名

  2. 服务端生成临时签名,并设置回调请求地址

  3. 客户端拿到签名、回调请求地址等信息后,将文件上传到 OSS

  4. OSS 完成文件存储后,按照回调地址将结果发送给服务器

  5. 服务器处理完后,将结果响应给 OSS

  6. 最后 OSS 将结果响应给客户端


这一块内容在文档中有详细的介绍,可以参考:

发布于: 刚刚阅读数: 3
用户头像

昆吾kw

关注

还未添加个人签名 2020-10-21 加入

还未添加个人简介

评论

发布
暂无评论
Nest 实现 OSS 签名直传上传回调_OSS_昆吾kw_InfoQ写作社区