使用GraphQL+Nest实现阿里云OSS上传

概述

服务端签名后直传的方式:

服务端签名后直传(Server Signature Direct Upload)是一种安全的文件上传方式,其中文件上传的签名是在服务端生成的,而不是在客户端生成。这样可以防止客户端直接上传文件而绕过服务器的权限控制。

这种方式的优点是可以在服务端进行更细粒度的控制,例如限制上传文件的大小、类型,以及存储路径等。客户端只需要负责文件上传,而上传权限和规则都由服务端掌控。这样可以提高文件上传的安全性和可控性。

安装aliyun的包 ali-oss

json 复制代码
"ali-oss": "^6.17.1",
"dayjs": "^1.11.7",
"buffer": "^6.0.3",

ali-oss (^6.17.1):

ali-oss 是阿里云 OSS(Object Storage Service)的官方 Node.js SDK。

用于在 Node.js 环境中与阿里云 OSS 进行交互,包括上传、下载、删除文件等操作。

允许在应用中直接使用 Node.js 代码访问和管理阿里云 OSS 中的对象。

dayjs (^1.11.7):

dayjs 是一个轻量级的 JavaScript 日期库,用于解析、操作和格式化日期。

与 Moment.js 相比,dayjs 更小巧,性能更好,同时提供了类似的功能,使日期处理更加方便。

buffer (^6.0.3):

buffer 是 Node.js 内置模块,用于处理二进制数据。

提供了对二进制数据的处理和转换功能,包括创建 Buffer 对象、拼接、切片等。

在文件处理、网络通信等场景中常用于处理二进制数据。

这些包在项目中的使用场景可能如下:

  • ali-oss:用于将文件上传到阿里云 OSS 或从 OSS 中下载文件。
  • dayjs:用于处理和格式化日期,提供更轻量级的替代方案。
  • buffer:在处理二进制数据时可能会使用,例如文件上传、数据流处理等。

对于server端,在modules中创建oss文件夹(oss对应的module),

创建oss.module.ts

此处展示完整代码,实际需要先创建oss.service,以及oss.resolver,再进行引入

python 复制代码
import { Module } from '@nestjs/common';
import { OSSService } from './oss.service';
import { OSSResolver } from './oss.resolver';

@Module({
  imports: [],
  providers: [OSSResolver, OSSService],
  exports: [],
})
export class OSSModule {}

providers: [OSSResolver, OSSService]: providers 数组包含了该模块提供的服务提供者。在这里,包括了 OSSResolver 和 OSSService,它们都是用 @Injectable() 装饰器装饰的服务类。

OSSResolver: 用于处理与 OSS 相关的 GraphQL 请求和操作。

OSSService: 提供获取阿里云 OSS 签名的服务

编写oss.service

配置oss相关 config

arduino 复制代码
 const config = {
      accessKeyId: 'LTAI5t6D9W6ArgXXXX',
      accessKeySecret: '8YNGXLtXXTOIRXXXXXnt',
      bucket: 'healthflex',
      dir: 'images/',
    };

这是一个配置对象,其中包含了一些用于连接和访问阿里云 OSS(Object Storage Service)的必要信息。

accessKeyId

该属性存储阿里云账户的 Access Key ID。

Access Key ID 用于标识阿里云账户,是访问和操作阿里云资源的身份标识。

accessKeySecret

该属性存储阿里云账户的 Access Key Secret。

Access Key Secret 是与 Access Key ID 配套使用的密钥,用于对请求的签名和验证。

bucket

bucket 是阿里云 OSS 中的存储桶,相当于一个命名空间,用于存储对象(文件)。

在这里,'healthflex' 是存储桶的名称,表示你要访问的特定存储桶。

dir

dir 表示上传文件时的目录,用于在存储桶内组织对象的存储结构。

在这里,'images/' 表示上传的文件将存储在存储桶的 'images/' 目录下。

这个配置对象通常会被用于初始化阿里云 OSS 客户端,在使用 ali-oss 等相关库的 API 时,作为参数传递给初始化的函数。这样,阿里云 OSS 客户端就能够使用这些信息来与指定的存储桶进行通信,执行文件上传、下载等操作。

文件上传服务由于要返回查询结果,所以要定义返回的类型OSSType

定义dto,添加返回对象的类型

less 复制代码
import { Field, ObjectType } from '@nestjs/graphql';

@ObjectType()
export class OSSType {
  @Field({ description: '过期时间' })
  expire: string;
  @Field({ description: '策略' })
  policy: string;
  @Field({ description: '签名' })
  signature: string;
  @Field({ description: 'key' })
  accessId: string;
  @Field({ description: 'host' })
  host: string;
}

以下是oss.service的完整代码

typescript 复制代码
import { Injectable } from '@nestjs/common';
import * as OSS from 'ali-oss';
import * as dayjs from 'dayjs';
import { OSSType } from './dto/oss.type';
@Injectable()
export class OSSService {
  //   获取签名
  async getSignature(): Promise<OSSType> {
    const config = {
      accessKeyId: 'LTAI5t8pPGHBcjAVASD3swxxD',
      accessKeySecret: 'kXkYy76asdasdcDQjdAXXXXXXXsaasdeasdfSlyM',
      bucket: 'healthflex',
      dir: 'images/',
    };
    const client = new OSS(config);

    const date = new Date();
    date.setDate(date.getDate() + 1);
    const policy = {
      expiration: date.toISOString(), // 请求有效期
      conditions: [
        ['content-length-range', 0, 1048576000], // 设置上传文件的大小限制
      ],
    };
    // bucket域名
    const host = `http://${config.bucket}.${
      (await client.getBucketLocation()).location
    }.aliyuncs.com`.toString();
    //签名
    const formData = await client.calculatePostSignature(policy);
    //返回参数
    const params = {
      expire: dayjs().add(1, 'days').unix().toString(),
      policy: formData.policy,
      signature: formData.Signature,
      accessId: formData.OSSAccessKeyId,
      host
    };
    return params;
  }
}

@Injectable(): 这是 NestJS 中的装饰器,用于标记这个类是一个可注入的服务(Service)。通过这个装饰器,NestJS 可以将这个类的实例注入到其他组件(如 Controller)中使用。

import * as OSS from 'ali-oss';: 使用 import * as 语法将整个 'ali-oss' 模块的所有导出内容放在一个名为 OSS 的对象中,以便在后续代码中使用。

async getSignature(): Promise: 这是一个异步方法,用于获取阿里云 OSS 的签名。返回一个 Promise,Promise 的值是一个类型为 OSSType 的对象。

const config = { ... };: 定义了用于创建 OSS 客户端的配置对象,包括阿里云的 Access Key、Bucket 名称和文件夹路径。

const client = new OSS(config);: 创建了阿里云 OSS 客户端实例。

const date = new Date(); ...: 创建了一个日期对象,然后计算了请求的有效期,并定义了上传文件的大小限制条件。

const formData = await client.calculatePostSignature(policy);: 使用 OSS 客户端计算了上传策略的签名,该签名将用于安全地将文件上传到 OSS。

const params = { ... };: 创建了一个包含签名等参数的对象,用于返回给调用方。

return params;: 返回包含签名等参数的对象,Promise 的结果。

这个服务类的目的是为前端应用提供获取阿里云 OSS 签名的功能,以便安全地上传文件到 OSS。

创建oss.resolver

typescript 复制代码
import { Query, Resolver } from '@nestjs/graphql';
import { OSSType } from './dto/oss.type';
import { OSSService } from './oss.service';
@Resolver()
export class OSSResolver {
  constructor(private readonly ossService: OSSService) {}
  @Query(() => OSSType, { description: '获取oss相关信息' })
  async getOSSInfo(): Promise<OSSType> {
    return await this.ossService.getSignature();
  }
}

@Resolver(): 这是 NestJS 中用于定义 GraphQL 解析器的装饰器。通过 @Resolver() 装饰器,可以将类标记为 GraphQL 解析器,并定义解析器中的查询和变更操作。

constructor(private readonly ossService: OSSService) {}: 解析器的构造函数接收一个参数 ossService,它是 OSSService 类的实例。这是通过 NestJS 的依赖注入系统注入的,用于在解析器中调用 OSSService 的功能。

@Query(() => OSSType, { description: '获取oss相关信息' }): 这是一个 GraphQL 查询操作的装饰器,表示下面的 getOSSInfo 方法是用于处理查询操作的。它的参数说明了该查询的返回类型是 OSSType,并提供了一个描述字符串。

async getOSSInfo(): Promise<OSSType>: 这是一个异步方法,用于处理 GraphQL 查询操作,返回一个 Promise,Promise 的值是一个类型为 OSSType 的对象。在该方法中,调用了 ossService.getSignature(),该方法是 OSSService 中的功能,用于获取阿里云 OSS 的签名信息。

总体来说,OSSResolver 类负责定义与 OSS 相关的 GraphQL 查询操作,它通过依赖注入系统使用 OSSService 提供的功能。在这个例子中,getOSSInfo 方法返回了获取的 OSS 签名信息,用于在前端应用中安全地上传文件到阿里云 OSS。

最终要记得在app.module.ts中引入oss.module

最终在graphql调试面板执行查询

markdown 复制代码
query getOSSInfo{
  getOSSInfo{
    expire
    policy
    signature
    accessId
    graphql
  }
}

总结

最终总结一下,对于服务端来说:

OSSModule(oss.module)

作用: OSSModule 是一个 NestJS 模块,用于组织和配置与 OSS 相关的功能。

构成:

导入模块:在示例中没有导入其他模块,但在实际应用中,可能需要导入其他相关的 NestJS 模块。

提供者:注册了 OSSResolver 和 OSSService,使它们在整个应用程序中可用。

OSSResolver(oss.resolver)

作用: OSSResolver 是一个 NestJS GraphQL 解析器,用于处理与 OSS 相关的 GraphQL 查询。

构成:

类装饰器:使用 @Resolver() 装饰器标记为一个 GraphQL 解析器类。

构造函数:接收 OSSService 的实例,通过依赖注入系统注入,用于在解析器中调用 OSS 相关服务。

查询操作:使用 @Query() 装饰器定义了查询操作 getOSSInfo,并指定了返回类型为 OSSType。

OSSService(oss.service)

作用: OSSService 是一个 NestJS 服务,提供了获取阿里云 OSS 签名的功能。

构成:

类装饰器:使用 @Injectable() 装饰器标记为一个可注入的服务类。

方法:包含了异步方法 getSignature,用于获取阿里云 OSS 的签名信息。

这三个部分一起构成了一个完整的后端服务的查询模块,用于处理前端应用发起的获取 OSS 签名的 GraphQL 查询。通过 NestJS 的依赖注入系统,OSSResolver 可以调用 OSSService 提供的功能,从而实现了模块内部的功能组合。前端应用可以通过调用 getOSSInfo 查询获取 OSS 相关信息,并使用这些信息在前端应用中安全地上传文件到阿里云 OSS。

相关推荐
Running_slave2 天前
搭建Nestjs+TypeORM+TS服务端应用架构
前端·后端·nestjs
东方小月3 天前
如何使用GitHub Actions自动部署我们的项目
前端·github·nestjs
Hello.Reader3 天前
GraphQL 全景攻略:从基础概念到生产落地的技术指南
后端·graphql
泰伦闲鱼5 天前
nestjs:GET REQUEST 缓存问题
服务器·前端·缓存·node.js·nestjs
求知若饥6 天前
NestJS 项目实战-权限管理系统开发(六)
后端·node.js·nestjs
白筱汐8 天前
Nestjs 和 Prisma 实现 Restful Api:JWT 授权
javascript·后端·nestjs
桂月二二10 天前
使用 Java 与 Spring Boot 实现高效 GraphQL API 开发
java·spring boot·graphql
mixboot12 天前
filecoin boost GraphQL API 查询
graphql·boost
寻找奶酪的mouse17 天前
告诉自己,请给予时间一点点耐心~
年终总结·nestjs
m0_7482368317 天前
API 接口选择那个?RESTful、GraphQL、gRPC、WebSocket、Webhook
websocket·restful·graphql