使用 graphql-upload、apollo-server-fastify 和 NestJS 代码优先方法上传文件

问题描述 投票:0回答:2

使用以下包/技术组合(以及未列出的相应依赖项)在服务器上接收来自客户端的文件上传的正确实现是什么:

  • graphql-upload
  • apollo-server-fastify
  • @nestjs/platform-fastify
    (代码优先方法)

理想情况下,我们尝试使用 NestJS GraphQL Code First 技术实现以下内容(来自 apollo 服务器文件上传)(多个文件而不是一个文件除外)

const { ApolloServer, gql } = require('apollo-server');

const typeDefs = gql`
  type File {
    filename: String!
    mimetype: String!
    encoding: String!
  }

  type Query {
    uploads: [File]
  }

  type Mutation {
    singleUpload(file: Upload!): File!
  }
`;

const resolvers = {
  Query: {
    uploads: (parent, args) => {},
  },
  Mutation: {
    singleUpload: (parent, args) => {
      return args.file.then(file => {
        //Contents of Upload scalar: https://github.com/jaydenseric/graphql-upload#class-graphqlupload
        //file.stream is a node stream that contains the contents of the uploaded file
        //node stream api: https://nodejs.org/api/stream.html
        return file;
      });
    },
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
});

server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

现在,我的前端正在使用此突变正确地将文件发送到我的服务器:

gql`
  mutation uploadObjects($files: [Upload!]!) {
    uploadObjects(files: $files) {
      bucketKey
    }
  }
`;

以下是与预期的文件二进制文件一起发送的请求图像的链接:

reactjs graphql nestjs apollo-server fastify
2个回答
0
投票

您可以将 graphql-upload 与 Apollo Server 和 NestJS 的 @nestjs/platform-fastify 一起使用。这个想法是使用 graphql-upload 作为中间件来处理来自客户端的文件上传。

首先,您需要更新 NestJS 的 main.ts 文件,以将 graphql-upload 与 Apollo 和 Fastify 集成。

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { graphqlUploadFastify } from 'graphql-upload';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter(),
  );

  // Apply the graphql upload middleware
  app.register(graphqlUploadFastify, {
    maxFileSize: 10000000, // 10 MB
    maxFiles: 5,
  });

  await app.listen(3000);
}
bootstrap();

然后,您需要在 GraphQL 模块中定义上传标量并更新解析器和架构以使用上传标量。这是一个如何做到这一点的示例。

在你的 app.module.ts:

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { join } from 'path';

@Module({
  imports: [
    GraphQLModule.forRoot({
      autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
      uploads: false, // Disable the built-in upload functionality of Apollo Server
    }),
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}

接下来,定义您的架构(例如 upload.schema.ts):

import { ObjectType, Field, InputType, Directive } from '@nestjs/graphql';

@ObjectType()
export class File {
  @Field()
  filename: string;

  @Field()
  mimetype: string;

  @Field()
  encoding: string;
}

@InputType()
@Directive('@extends')
@Directive('@key(fields: "id")')
export class Upload {
  @Field()
  id: string;
}

以及相应的解析器(例如,upload.resolver.ts):

import { Resolver, Mutation, Args, Query } from '@nestjs/graphql';
import { FileUpload, GraphQLUpload } from 'graphql-upload';
import { createWriteStream } from 'fs';
import { File } from './upload.schema';

@Resolver()
export class UploadResolver {
  @Query(() => [File])
  async uploads(): Promise<File[]> {
    // Implement the logic to return the files
    return [];
  }

  @Mutation(() => Boolean)
  async uploadObjects(@Args({ name: 'files', type: () => [GraphQLUpload] }) files: FileUpload[]): Promise<boolean> {
    await Promise.all(
      files.map(async file => {
        const { createReadStream, filename } = await file;
        // Create a stream to your file destination.
        // Here is an example of saving the file locally
        return new Promise((resolve, reject) =>
          createReadStream()
            .pipe(createWriteStream(`./uploads/${filename}`))
            .on('finish', () => resolve(true))
            .on('error', (error) => reject(error)),
        );
      }),
    );

    return true;
  }
}

在此实现中,您使用 Fastify 作为 HTTP 服务器而不是默认服务器 (Express) 和 graphql-upload 中间件来处理文件上传。中间件通过文件上传解析传入请求,并将流传递到解析器。请注意,在@Mutation装饰器中,我们使用的是graphql-upload提供的GraphQLUpload,这是文件上传所需的格式。

请确保安装了所有必需的软件包。如果没有,请使用npm或yarn安装它们:

npm install @nestjs/graphql graphql-tools graphql apollo-server-fastify fastify multipart graphql-upload

-1
投票

使用 Amazon S3 进行文件存储并结合 GraphQL 文件上传可在可扩展性、可靠性和成本效益方面提供多种优势。 S3 是 AWS 提供的一种高度可扩展且持久的对象存储服务,旨在以高可用性处理大量数据。通过将文件存储卸载到 S3,您可以利用其内置功能,例如自动版本控制、访问控制和生命周期策略。此外,S3 还提供生成

signed URLs
的功能,允许您在有限的时间内与客户安全地共享私人文件。这在不需要直接访问存储后端并且您希望以编程方式控制和跟踪文件访问的情况下特别有用。此外,S3 提供按需付费的定价模式,仅对所使用的存储和带宽进行收费,从而确保成本效率,使其成为基于云的应用程序中可扩展且经济高效的文件管理的最佳选择。

© www.soinside.com 2019 - 2024. All rights reserved.