简体   繁体   中英

Angular / Nest / GraphQL - Unable to make file upload (either 400 bad request or 500)

From what I've seen online everything here should work, in practive I receive 400 bad request from the client and 500 (wrong order) from postman

// app.module.ts
 GraphQLModule.forRoot({
      cors: true,
      playground: true,
      debug: true,
      autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
      // installSubscriptionHandlers: true,
      uploads: true,
      context: ({ req, res }) => ({
        req,
        res,
      }),
// File upload mutation in random resolver
  @Mutation(() => ResponseMessage)
  async uploadSigleFile(
    @Args({ type: () => GraphQLUpload, name: 'upload', nullable: true })
    upload: FileUpload,
  ) {
    console.log(upload.filename, upload.mimetype);
    return new ResponseMessage({ response: 'ciao' });
  }

Graphql link where I enabled multipart data (in fact the request correctly shows up as multipart)

const uri = `${environment.serverUrl}/graphql`; // <-- add the URL of the GraphQL server here
export function createApollo(httpLink: HttpLink): ApolloClientOptions<any> {
  return {
     link: httpLink.create({ uri, useMultipart: true }),
    cache: new InMemoryCache()
  };
}

@NgModule({
  exports: [ApolloModule, HttpLinkModule],
  providers: [
    {
      provide: APOLLO_OPTIONS,
      useFactory: createApollo,
      deps: [HttpLink]
    }
  ]
})
export class GraphQLModule {}

Graphql mutation that generates the angular service

mutation Super($upload: Upload) {
  uploadSigleFile(upload: $upload) {
    response
  }
}

Where the mutation gets called (yes I checked and the files actually arrives to the mutation)

  onFileChange(e: HTMLInputEvent) {
    const myFile = e.target.files[0];
    this.apolloQuery(myFile);
  }

  apolloQuery(upload: File) {
    this.superGql
      .mutate({
        upload
      })
      .subscribe(({ errors, context, data, extensions }) => {

      });
  }

This is driving me crazy, I'll be eternally grateful to whoever helps, I have tried any possible combination, I don't know what I'm missing (ex: custom nest scalar, or importing it in the resolvers field, using apollo-client-upload in the client)

Yeah so in the end apollo automatically parses multipart requests, and using a scalar in the code-first-approach resulted in having it parsed 2 times (makes no sense but whatever)

So in the end I just had to write an upload custom nest scalar that did absolutely nothing

import { Scalar, CustomScalar } from '@nestjs/graphql';
// FileUpload is just an interface, not really useful in any way here, just to be // explicit of what type comes out whenever I want to check out the scalar
import { FileUpload } from 'graphql-upload';

@Scalar('Upload')
export class UploadScalar implements CustomScalar<object, any> {
  description = 'Upload custom scalar type';


// the value arrives here already parsed
  parseValue(value: FileUpload) {
    return value;
  }


  // You dont use this
  serialize(value: any) {
    return null;
  }

  // You dont use this
  parseLiteral(ast) {
    return null;
  }
}
//app.module.ts
GraphQLModule.forRoot({
      autoSchemaFile: join(process.cwd(), 'schema.graphql'),
      context: req => ({ req }),
      uploads: true,
    })

// random.resolver.ts
@Query(() => MainObject)
  async boh(
    @Args({ name: 'file', type: () => FileUpload, nullable: true })
    file: FileUpload,
  ) {
    return new Promise((resolve, reject) => {
      const read = file.createReadStream();
      const write = fs.createWriteStream(path.join(process.cwd(), 'file3.csv'));
      read.pipe(write);
      read.on('close', () => {
        resolve(new MainObject({ response: 'tutto ok', age: 200 }));
      });
    });
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM