Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
496 views
in Technique[技术] by (71.8m points)

apollo - Getting the infamous 400 error from graphql when uploading a file, debug shows data populated in graphql-upload

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!) {
' +
? ? ' ?createDocument(file: $file, name: $name) {
' +
? ? ' ? ?id
' +
? ? ' ? ?name
' +
? ? ' ? ?__typename
' +
? ? ' ?}
' +
? ? '}
'
}
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!) {
 ?createDocument(file: $file, name: $name) {
 ? ?id
 ? ?name
 ? ?__typename
 ?}
}
"}
------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>
question from:https://stackoverflow.com/questions/65887500/getting-the-infamous-400-error-from-graphql-when-uploading-a-file-debug-shows-d

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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 });

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...