Last edit: Oct 26, 2022

Uploads are used to store the URL and metadata of a file that the user uploaded.


You can define uploads by adding a property with type set to upload, for example:

- name: document
  type: upload


Property upload takes an extra options parameter, which allows you to configure it.

Option Description
acl If set to public (default) the file will be publicly available. If set to private, a signature generated on the server-side will be needed in order to access the file. It will be automatically generated by GraphQL when you provide the expires_in argument to the property_upload GraphQL method.
content_length Allows you to set server-side validation for minimum (using gte key) and maximum file size (using lte key) in kilobytes. For example, lte: 2048 will set the max input file size (not the generated version) to 2MB.
versions Allows you to define up to 10 versions of the image. For each version you can define multiple different processing instructions - compression, resizing, etc. This option will be ignored if the uploaded file is not an image. Visit List versions options
cache_control Allows you to set the Cache-Control header returned with the file. Default is max-age=315576000, public
content_disposition Allows you to set the Content-Disposition header. Default is inline, you can change it to attachment.


Versions are defined in yml as an array. Each element must have a name and then a list of options you want to use. Please note that not all combinations make sense. An example configuration might look like this:

- name: photo
  type: upload
      lte: 2048  # maximum input file size will be 2048 KB
      - name: large_bw    # version name
          format: jpeg    # output format
          quality: 70     # output quality
          width: 1600     # width of the image - in this case max width
          height: 1200    # height of the image - in this case max height
          fit: inside     # preserve aspect ratio, do not crop the image, make sure all pixels are within viewport
          without_enlargement: false              # if image is smaller than width/height, do not enlarge it
          greyscale: true   # make image greyscale (similar to css "filter: grayscale(1)")
          blur: 20          # blur using gaussian mask (similar to css "filter: blur(1.5rem)")
          flatten: red      # merge alpha transparency channel (if exists) with given color
      - name: small
          format: webp
          quality: 80
          width: 640
          height: 480
          fit: cover
          position: top   # define the gravity direction or strategy when cropping the image using fit cover or contain
      - name: thumb
          format: png
          quality: 80
          width: 200
          fit: contain
          background: "rgba(255, 255, 255, 0.5)"  # if the resized image is not covering whole viewport, set background color, can be in hex format (ie. #f0f0f0), or rgb (ie. rgb(255, 255, 255))
      - name: center
          format: jpeg
          quality: 100
          height: 400
          width: 400
          fit: cover

This is exactly the same configuration which we have used in our examples site to demonstrate Direct s3 upload with uppy. Try it out by going to the Direct S3 upload images and uploading an image. Please note that you will need to create a free account to access that page if you don't have one yet.


format [String] - Force Extension of an output image, leave blank if you want to keep the format of the original image.

quality Int - Quality of the output. 100 being the best (and largest in terms of size). Keep in mind compression has different effects on different formats. Defaults: PNG: 80, WEBP: 80, JPEG: 85

progressive [Boolean] - Only format: jpeg - use progressive (interlace) scan. Default: true


width [Int] - width that the user passed as a reference. If left undefined, will depend on other parameters to determine size (like: height)
height [Int] - height that the user passed as a reference. If left undefined, will depend on other parameters to determine size (like: width)

fit [String] (cover, contain, fill, inside, outside) - how the image should be resized to fit both provided dimensions

  • cover: Crop to cover both provided dimensions (the default).
  • contain: Embed within both provided dimensions.
  • fill: Ignore the aspect ratio of the input and stretch to both provided dimensions.
  • inside: Preserving aspect ratio, resize the image to be as large as possible while ensuring its dimensions are less than or equal to both those specified.
  • outside: Preserving aspect ratio, resize the image to be as small as possible while ensuring its dimensions are greater than or equal to both those specified. Some of these values are based on the object-fit CSS property.

position [String] (top, right top, right, right bottom, bottom, left bottom, left, left top) - position to use when fit is cover or contain. default: center

background [String|Object] - background color when using a fit of contain, parsed by the color module, defaults to black without transparency. Default: #000000 or { r: 0, g: 0, b: 0, alpha: 1 }.

without_enlargement [Boolean] - do not enlarge if the width or height are already less than the specified dimensions. default: false


greyscale [Boolean] - Convert to 8-bit greyscale; 256 shades of grey. Default: false

blur [Int|Float] (0.3 - 1000) - value representing the sigma of the Gaussian mask, where sigma = 1 + radius / 2

flatten [String|Object] - Default: #000000 or { r: 0, g: 0, b: 0 }

Sending the upload to the server

To store an upload, you need to first upload a physical file directly to S3. When you do it successfully, you will receive an URL to the actual file - you need to store this URL in the property. This process is described in detail in User Upload.

Fetching an upload from a server

In order to fetch the URL of the uploaded image, you need to use property_upload. p argument to generate the signature to access the private file. The signature will automatically expire after the number of seconds you specify. Please note, you will not be able to access the URL when you fetch all properties at once using properties in your GraphQL query, as the URL is generated on the fly inside the property_upload method.

You can check the example code of how to store the URL and then retrieve it in the next guide - User Upload

Contribute to this page

Github Icon


We are always happy to help with any questions you may have.

contact us