Reputation: 1284
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)
Upvotes: 0
Views: 1047
Reputation: 1284
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 }));
});
});
}
Upvotes: 1