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>