0

I know this is a common issues, and I've made sure the app is sending the right data. I've even added logging to show that the fields are being populated correctly.

The one thing I noticed is the console.log I have inside parser.once('finish' () => {}) wasn't being called, which is where the "Missing multipart field" error should be coming from.  Any insight would be appreciated.

progressRequest - operations called {
  variables: { file: null, name: 'test' },
  query: 'mutation ($file: Upload!, $name: String!) {\n' +
    '  createDocument(file: $file, name: $name) {\n' +
    '    id\n' +
    '    name\n' +
    '    __typename\n' +
    '  }\n' +
    '}\n'
}
processRequest - map called { '1': [ 'variables.file' ] }
processRequest - map entries [ [ '1', [ 'variables.file' ] ] ]
processRequest - map complete Map(1) {
  '1' => Upload {
    resolve: [Function (anonymous)],
    reject: [Function (anonymous)],
    promise: Promise { <pending> }
  }
}
processRequest - release Map(1) {
  '1' => Upload {
    resolve: [Function (anonymous)],
    reject: [Function (anonymous)],
    promise: Promise { [Object] },
    file: {
      filename: 'file.docx',
      mimetype: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      encoding: '7bit',
      createReadStream: [Function: createReadStream]
    }
  }
}
BadRequestError: Missing multipart field ‘operations’ (https://github.com/jaydenseric/graphql-multipart-request-spec).

Client post has the following:

------WebKitFormBoundaryVcAmZ4u9BOEmAIVW
Content-Disposition: form-data; name="operations"

{"variables":{"file":null,"name":"test"},"query":"mutation ($file: Upload!, $name: String!) {\n  createDocument(file: $file, name: $name) {\n    id\n    name\n    __typename\n  }\n}\n"}
------WebKitFormBoundaryVcAmZ4u9BOEmAIVW
Content-Disposition: form-data; name="map"

{"1":["variables.file"]}
------WebKitFormBoundaryVcAmZ4u9BOEmAIVW
Content-Disposition: form-data; name="1"; filename="file.docx"
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document


------WebKitFormBoundaryVcAmZ4u9BOEmAIVW--  

Server Typescript:

import { FileUpload, GraphQLUpload } from "graphql-upload";
import { Mutation, Arg, Resolver } from "type-graphql";
import { Document } from "../Document";

@Resolver(Document)
export class DocumentResolver {

    @Mutation(() => Document)
    async createDocument(@Arg("name") name: string, @Arg("file", () => GraphQLUpload) file: FileUpload): Promise<Document> {
        console.warn(name, file);        
        return null; // dont care about getting anything back as long as I see my console message
    };
}

Client Typescript:

import { Component } from "@angular/core";
import { Apollo, gql } from "apollo-angular";

@Component({
  selector: 'test-page',
  templateUrl: './test.html'
})
export class TestPageComponent {

  constructor(private apollo: Apollo) { }

  public onFileSelected(e: any): void {
    if (e.target.validity.valid) {
      this.serverResponse = {};
      this.serverResponseErr = {};

      let file = e.target.files[0];
      this.loadFileApollo(file);
    }
  }

  public loadFileApollo(file: File): void {
    const GRAPHQL_CREATE_TEMPLATE = `
    mutation($file: Upload!, $name: String!) {
      createDocument(file: $file, name: $name) {
        id,
        name
      }
    }`;
    // 
    //var ti = { file: file };
    this.apollo.mutate<any>({
      mutation: gql(GRAPHQL_CREATE_TEMPLATE),
      variables: { file: file, name: "test" },
      context: {
        useMultipart: true
      }
    }).subscribe(x=> console.warn(x));
  }
}

HTML:

  <div>
    Click this button to select a file and immediately upload it to the server
    <input class="btn btn-primary" type="file" (change)="onFileSelected($event)"/>
  </div>
Vince
  • 757
  • 1
  • 8
  • 16

1 Answers1

1

So the problem is with Apollo's internal implementation of graphql-upload. If you are autogenerating your schema I would advise you to disable their upload and implement graphql-upload directly. They are quite a few versions behind and it was having issues sending requests between the two implementations.

ApolloServer({ uploads: false });
Vince
  • 757
  • 1
  • 8
  • 16