Skip to main content

Storage

Nhost Storage enables you to let your users upload and download files. Nhost Storage is partially integrated with the GraphQL API, where file metadata and permissions are managed. Files are stored in S3 and served via a CDN.

Files

Files can be of any type, such as images, documents, videos, etc.

File metadata is stored in your database in the files table in the storage schema. This means that file metadata is available in your GraphQL API, which makes it easy to:

  • Read file metadata via GraphQL.
  • Manage file permissions (in Hasura).
  • Create GraphQL relationships between files and your database tables.
danger

Don't modify the database schema, nor GraphQL root fields in any of the tables in the storage schema.

tip

You're allowed to add and modify the following:

  • GraphQL Relationships
  • Permissions

Upload File

When a file is uploaded, the file metadata is inserted into the storage.files table and a file id is returned. The file's id is how you reference and access the file. It's recommended to create your own table to store the uploaded file id, to access the file in the future.

POST /v1/storage/files HTTP/1.1

Download File

There are two ways to download a file:

  • Public URL.
  • Pre-signed URL.

Public URL

Public URLs are available for both unauthenticated and authenticated users. Permissions are checked for every file request. To get a public URL for a file, you would normally use the public role to set select permissions.

GET /v1/storage/files/{file_id} HTTP/1.1

Pre-signed URL

Pre-signed URLs work a bit differently from public URLs.

The permission check only happens when the user requests a pre-signed URL. Once a pre-signed URL is generated, anyone with the pre-signed URL can download the file.

Pre-signed URLs expire, and stop work, after a set amount of time. By default, for files in the default bucket, the expiration time is 30 seconds. You can change the expiration time for pre-signed URLs by changing the download_expiration (in seconds) field on the bucket where the file is located.

GET /v1/storage/files/{file_id}/presignedurl HTTP/1.1

Delete File

Delete a file and the file metadata in the database.

DELETE /v1/storage/files/{file_id} HTTP/1.1

Buckets

Buckets are used to organize files and group permissions for files. Buckets are stored in the storage.buckets table in your database, and accessible via buckets in your GraphQL API.

For each Bucket, you can specify file permissions for the following properties:

  • MIME type.
  • Minimum size in bytes.
  • Maximum size in bytes.
  • Cache control.
  • Allow pre-signed URLs.
  • Download expiration (for pre-signed URLs).

There is a default Bucket (default) that is used if no Bucket is specified during file upload. It's not possible to delete the default Bucket.

Permissions

Permissions to upload, download, and delete files are managed through Hasura's permission system on the storage.files table.

Upload

To upload a file, a user must have the insert permission to the storage.files table. The id column must be granted.

The following columns can be used for insert permissions:

  • id
  • bucket_id
  • name
  • size
  • mime_type

Download

To download a file, a user must have the select permission to the storage.files table. All columns must be granted.

Delete

To delete a file, a user must have the delete permission to the storage.files table.

Updating an existing file is not supported. If you need to update a file, delete the file and upload a new file.

Just deleting the file metadata in the storage.files table does not delete the actual file. Always delete files via Nhost Storage. This way, both the file metadata and the actual file are deleted.

Image Transformation

Images can be transformed, on the fly, by adding query parameters. The following query parameters are available:

  • w - Width of the image in pixels.
  • h - Height of the image in pixels.

Image Transformation works on both public and pre-signed URLs.

Example: Transform an image to 500px width (?w=500):

https://[subdomain].nhost.run/v1/storage/files/08e6fa32-0880-4d0e-a832-278198acb363?w=500

Example: CRM System

Let's say you want to build a CRM system and you want to store files for customers. This is one way how you could do that.

Start with, you would have two tables:

  1. customers - Customer data.
  2. customer_files - What file belongs to what customer
- customers
- id
- name
- address

customer_files
- id
- customer_id (Foreign Key to `customers.id`)
- file_id (Foreign Key to `storage.files.id`)

You would also create a Hasura Relationship (GraphQL relationship) between between customers and customer_files and between customer_files and storage.files.

With the two tables and GraphQL relationships in place, you can query customers and the customer's files like this:

query {
customers {
# customers table
id
name
customer_files {
# customer_files table
id
file {
# storage.files table
id
name
size
mimeType
}
}
}
}

The file upload process would be as follows:

  1. Upload a file.
  2. Get the returned file id.
  3. Insert (GraphQL Mutation) the file id and the customer's id into the customer_files table.

This would allow you to upload and download files belonging to specific customers in your CRM system.