Skip to content

Document file upload handling for GraphQL #913

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 57 additions & 3 deletions core/file-upload.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Controller\CreateMediaObjectAction;
use App\Resolver\CreateMediaObjectResolver;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Serializer\Annotation\Groups;
Expand Down Expand Up @@ -83,6 +84,15 @@ use Vich\UploaderBundle\Mapping\Annotation as Vich;
* itemOperations={
* "get",
* },
* graphql={
* "upload"={
* "mutation"=CreateMediaObjectResolver::class,
* "deserialize"=false,
* "args"={
* "file"={"type"="Upload!", "description"="The file to upload"}
* }
* },
* },
* )
* @Vich\Uploadable
*/
Expand Down Expand Up @@ -129,8 +139,9 @@ class MediaObject

## Handling File Upload

At this point, the entity is configured, but we still need to write the action
that handles the file upload.
At this point, the entity is configured, but we still need to write the handler for the uploaded file.

### REST

```php
<?php
Expand Down Expand Up @@ -159,6 +170,32 @@ final class CreateMediaObjectAction
}
```

### GraphQL

```php
<?php
// api/src/Resolver/CreateMediaObjectResolver.php

namespace App\Resolver;

use ApiPlatform\Core\GraphQl\Resolver\MutationResolverInterface;
use App\Entity\MediaObject;
use Symfony\Component\HttpFoundation\File\UploadedFile;

final class CreateMediaObjectResolver implements MutationResolverInterface
{
public function __invoke($item, array $context): MediaObject
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing @param.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment below - it's the same as the existing REST example.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The REST __invoke doesn't need a PHPDoc (since it's already typehinted), but it's useful here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, makes sense. We do not use the $item here, but I'll describe that as well 👍

{
$uploadedFile = $context['args']['input']['file'];

$mediaObject = new MediaObject();
$mediaObject->file = $uploadedFile;

return $mediaObject;
}
}
```

## Resolving the File URL

Returning the plain file path on the filesystem where the file is stored is not useful for the client, which needs a
Expand Down Expand Up @@ -227,7 +264,9 @@ final class ResolveMediaObjectContentUrlSubscriber implements EventSubscriberInt
}
```

## Making a Request to the `/media_objects` Endpoint
## Making a Request to upload a file

### REST

Your `/media_objects` endpoint is now ready to receive a `POST` request with a
file. This endpoint accepts standard `multipart/form-data`-encoded data, but
Expand All @@ -242,6 +281,21 @@ your data, you will get a response looking like this:
}
```

### GraphQL

You can now upload files using the `createMediaObject` mutation, for details check [graphql-multipart-request-spec](https://github.com/jaydenseric/graphql-multipart-request-spec) and for an example implementation for the Apollo client check out [apollo-upload-client](https://github.com/jaydenseric/apollo-upload-client).

```graphql
mutation CreateMediaObject($file: Upload!) {
createMediaObject(input: {file: $file}) {
mediaObject {
id
contentUrl
}
}
}
```

## Linking a MediaObject Resource to Another Resource

We now need to update our `Book` resource, so that we can link a `MediaObject`
Expand Down