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>
1
  • We gave up on any file uploads and just convert whatever we need to send into base64 content, this made implementation much easier. Commented Oct 16, 2023 at 19:38

1 Answer 1

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 });
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.