
Uploading files with GraphQL in Symfony
File uploads are a common thing in web development and you can most often see it in action when you try to change your account’s profile picture. GraphQL doesn’t have a file as a type defined by the specification, but a GraphQL community found a solution.
There is aspec that’s widely used in the Apollo ecosystem withapollo-upload-client andapollo-server, which allows us to send multipart requests to the GraphQL server. In the Symfony world, Overblog’sGraphQLBundle is one of the most popular options with support for both Apollo and Relay. This bundle also supports file uploads out of the box by providing Upload type and resolving it toUploadedFile
object that’s commonly seen in Symfony when working with uploaded files.
Define your schema
In this example we will work with a single Author entity that consists of 3 fields:firstName
,lastName
andpictureFilename
. GraphQL type definition should have exactly the same fields.
Author:type:objectconfig:fields:id:type:"ID!"firstName:type:"String!"lastName:type:"String!"profileFilename:type:"String!"
Here, we also need only one mutation with arguments for required data and Author type as output. Instead of thepictureFilename
defined in Author type, here we will usepicture
as an argument name.
Mutation:type:objectconfig:fields:CreateAuthor:type:'Author!'resolve:'@=mutation("App\\GraphQL\\Mutation\\AuthorMutation::createAuthor", [args["firstName"], args["lastName"], args["picture"]])'args:firstName:type:String!lastName:type:String!picture:type:AuthorPictureUploadFile!
As you can see, we used custom type for the profile picture field and that is where most of the magic happens. Now, the only thing missing in the schema is to add a definition for it by extending the Upload type provided by bundle.
AuthorPictureUploadFile:type:custom-scalarconfig:scalarType:'@=newObject("Overblog\\GraphQLBundle\\Upload\\Type\\GraphQLUploadType")'
Handling files in mutation
Now, when we have the schema defined, we can add the mutation logic. In the Mutation type definition, we already specified our mutation class and how it will pass arguments to itscreateAuthor
method. Because the bundle will transform uploaded files toUploadedFile
objects before passing them to the mutation, we can easily move them to the desired folder and use the filename to populate entity data.
classAuthorMutationimplementsMutationInterface{...publicfunctioncreateAuthor(string$firstName,string$lastName,UploadedFile$picture):Author{$filename=uniqid('author_picture_').'.'.$picture->guessExtension();$picture->move($this->uploadsPath,$filename);$author=newAuthor();$author->setFirstName($firstName);$author->setLastName($lastName);$author->setPictureFilename($filename);$this->entityManager->persist($author);$this->entityManager->flush();return$author;}}
Conclusion
Uploading files with GraphQL is simple and easy with multipart specification widely supported by Apollo and its ecosystem. Even without the official specification regarding uploads, there are a few options available, but the one shown in this post is probably the simplest. Additionally, Symfony also has a great GraphQL bundle to provide server-side runtime with features like batching, file uploads and much more.
If you have any questions, comments or experiences with using GraphQL you'd like to share, put them in the comments section below!
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse