GraphQL Compose: File upload
Security covered
Graphql ecosystem
This project enables file uploads through GraphQL mutations using the "Multipart HTTP Request" standard. It validates uploads against field settings and supports any file field on any entity type, returning detailed error information for invalid uploads.
About
Enable file upload mutations for GraphQL using the Multipart HTTP Request. Based on module graphql_compose.
Features
- Upload files via GraphQL mutations
- Validates file uploads against field instance settings
- Supports any file field on any entity type
- Returns proper error violations for invalid uploads
- Based on the GraphQL Compose schema
Requirements
- Drupal: 10.1+
- PHP: 8.1+
- Module: graphql_compose
Usage
GraphQL Mutation
The module adds a fileUpload mutation to the GraphQL schema:
mutation UploadFile($file: Upload!, $metadata: fieldMetadata!) {
fileUpload(file: $file, metadata: $metadata) {
errors {
message
}
results {
entity {
... on File {
id
url
filename
}
}
}
}
}
Metadata Input
The fieldMetadata input requires:
field_name
String!
The machine name of the file field
entity_type
EntityType!
The entity type (node, user, etc.)
entity_bundle
String!
The bundle of the entity
Example: Upload a File
JS example
const operation = {
query: `
mutation UploadFile($file: Upload!, $metadata: fieldMetadata!) {
fileUpload(file: $file, metadata: $metadata) {
errors {
message
}
results {
entity {
... on File {
id
url
filename
mimetype
filesize
}
}
}
}
}
`,
variables: {
file: null, // Set by FormData
metadata: {
field_name: 'field_document',
entity_type: 'node',
entity_bundle: 'article',
},
},
};
const formData = new FormData();
formData.append('operations', JSON.stringify(operation));
formData.append('map', JSON.stringify({ 0: ['variables.file'] }));
formData.append(0, fileUpload);
fetch('https://example.com/graphql', {
method: 'POST',
body: formData,
});
curl example
# Create file
curl https://example.com/graphql \
-F operations='{ "query": "fileUploadMutation ($file: Upload!) { fileUpload( file: $file, metadata: { field_name: \"field_my_file\", entity_type: NODE, entity_bundle: \"event\" } ) { errors results { entity_bundle entity_type id values } }}", "variables": { "file": null }}' \
-F map='{ "0": ["variables.file"] }' \
-F 0=@/path/to/myfile.pdf
# Create image
curl https://example.com/graphql \
-F operations='{ "query": "mutation ($file: Upload!) { fileUpload( file: $file, metadata: { field_name: \"field_my_file\", entity_type: NODE, entity_bundle: \"event\" } ) { errors results { entity_bundle entity_type id values } }}", "variables": { "file": null }}' \
-F map='{ "0": ["variables.file"] }' \
-F 0=@/path/to/myimage.jpeg
Response Type
The mutation returns an AnyFileUploadResponse with:
errors
[Violation]
Array of validation violations (if any)
results
AnyEntity
The uploaded file entity
Security
- File uploads are validated against Drupal's field instance settings
- File size restrictions are enforced
- Allowed file extensions are validated
- Access control respects Drupal's permissions
Troubleshooting
Upload returns validation errors
Check that:
- The field exists on the specified entity bundle
- The file extension is allowed by the field settings
- The file size is within limits
- The user has permission to create files
File is not saved
Ensure:
- The file system is writable
- The upload directory exists and is configured
- PHP's
upload_max_filesizeandpost_max_sizeare sufficient