Uploading files using signed URLs is a more involved process. What we'll implement is a 3-phase dance between the backend and the frontend so that users can add new images to their collection. By using signed URLs we make sure there is no implicit limit on the file sizes and it plays well with AppSync's serverless nature.
The first step is for the frontend to request an upload URL from the backend. In the GraphQL schema, this is a Query that returns a JSON:
type Query {
getUploadURL: AWSJSON!
}
S3 signed URLs can be PUT and POST. PUT URLs encode everything in the URL itself making them easier to use, but they also lack some finer control over the file upload process, such as setting a limit on the file size. POST signed URLs have other fields besides the URL itself, one of them a policy that can define restrictions on different aspects on the uploaded files.
When the client is capable of handling forms then using POST signed URLs is always the better choice. The getUploadURL
field in the GraphQL schema has AWSJSON
as a type so that it can return the form fields for the signed URL.
The second step is that the client uploads the file by dynamically constructing and submitting a form with the fields of the signed URL it got from the backend. This happens in the background using JavaScript and it does not involve any interaction from the user.
The third step is that the client calls the backend again when the file is uploaded successfully. This will be a mutation in the GraphQL schema:
type Mutation {
addImage(key: ID!): Image!
}
This gives a chance for the backend to update a database to point to the new file. In our case, it will insert a row into a DynamoDB table so that later queries will receive the new file.