# Upload

Thanks to the plugin Upload, you can upload any kind of file on your server or external providers such as AWS S3.

# Configuration

Currently the Strapi middleware in charge of parsing requests needs to be configured to support file sizes larger than the default of 200MB.

The library we use is koa-body (opens new window), and it uses the node-formidable (opens new window) library to process files.

You can pass configuration to the middleware directly by setting it in the body middleware configuration in ./config/middleware.js:

# Responsive Images

When the Enable responsive friendly upload setting is enabled in the settings panel the plugin will generate the following responsive image sizes:

Name Largest Dimension
large 1000px
medium 750px
small 500px

These sizes can be overridden in ./config/plugins.js:

✋ CAUTION

Breakpoint changes will only apply to new images, existing images will not be resized or have new sizes generated.

# Endpoints

Method Path Description
GET /api/upload/files Get a list of files
GET /api/upload/files/:id Get a specific file
POST /api/upload Upload files
DELETE /api/upload/files/:id Delete a file

# Upload files

To upload files into your application.

# Parameters

  • files: The file(s) to upload. The value(s) can be a Buffer or Stream.

# Code example

<form>
  <!-- Can be multiple files -->
  <input type="file" name="files" />
  <input type="submit" value="Submit" />
</form>

<script type="text/javascript">
  const formElement = document.querySelector('form');

  formElement.addEventListener('submit', (e) => {
    e.preventDefault();

    const request = new XMLHttpRequest();

    request.open('POST', '/upload');

    request.send(new FormData(formElement));
  });
</script>

✋ CAUTION

You have to send FormData in your request body.

# Upload files related to an entry

To upload files that will be linked to a specific entry.

# Request parameters

  • files: The file(s) to upload. The value(s) can be a Buffer or Stream.
  • path (optional): The folder where the file(s) will be uploaded to (only supported on strapi-provider-upload-aws-s3).
  • refId: The ID of the entry which the file(s) will be linked to.
  • ref: The unique ID (uid) of the model which the file(s) will be linked to (see more below).
  • source (optional): The name of the plugin where the model is located.
  • field: The field of the entry which the file(s) will be precisely linked to.

# Examples

The Restaurant model attributes:

// path: ./src/api/restaurant/content-types/restaurant/schema.json

{
  // ...
  "attributes": {
    "name": {
      "type": "string"
    },
    "cover": {
      "type": "media",
      "multiple": false,
    }
  }
// ...
}

Code

<form>
  <!-- Can be multiple files if you setup "collection" instead of "model" -->
  <input type="file" name="files" />
  <input type="text" name="ref" value="api::restaurant.restaurant" />
  <input type="text" name="refId" value="5c126648c7415f0c0ef1bccd" />
  <input type="text" name="field" value="cover" />
  <input type="submit" value="Submit" />
</form>

<script type="text/javascript">
  const formElement = document.querySelector('form');

  formElement.addEventListener('submit', (e) => {
    e.preventDefault();

    const request = new XMLHttpRequest();

    request.open('POST', '/upload');

    request.send(new FormData(formElement));
  });
</script>

✋ CAUTION

You have to send FormData in your request body.

# Upload file during entry creation

You can also add files during your entry creation.

# Examples

The Restaurant model attributes:

// path: ./src/api/restaurant/content-types/restaurant/schema.json

{
  // ...
  "attributes": {
    "name": {
      "type": "string"
    },
    "cover": {
      "type": "media",
      "multiple": false,
    }
  }
  // ...
}

Code

<form>
  <!-- Can be multiple files if you setup "collection" instead of "model" -->
  <input type="text" name="name" />
  <input type="file" name="cover" />
  <input type="submit" value="Submit" />
</form>

<script type="text/javascript">
  const formElement = document.querySelector('form');

  formElement.addEventListener('submit', (e) => {
    e.preventDefault();

    const request = new XMLHttpRequest();

    const formData = new FormData();

    const formElements = formElement.elements;

    const data = {};

    for (let i = 0; i < formElements.length; i++) {
      const currentElement = formElements[i];
      if (!['submit', 'file'].includes(currentElement.type)) {
        data[currentElement.name] = currentElement.value;
      } else if (currentElement.type === 'file') {
        for (let i = 0; i < currentElement.files.length; i++) {
          const file = currentElement.files[i];
          formData.append(`files.${currentElement.name}`, file, file.name);
        }
      }
    }

    formData.append('data', JSON.stringify(data));

    request.open('POST', `${HOST}/restaurants`);

    request.send(formData);
  });
</script>

Your entry data has to be contained in a data key. You have to JSON.stringify your data object.

And for your files, they have to be prefixed by files. Example here with cover attribute files.cover.

💡 TIP

If you want to upload files for a component, you will have to specify the index of the item you want to add the file to. Example files.my_component_name[the_index].attribute_name

✋ CAUTION

You have to send FormData in your request body.

# Models definition

Adding a file attribute to a model (or the model of another plugin) is like adding a new association.

In the first example below, you will be able to upload and attach one file to the avatar attribute.

// path: ./src/api/restaurant/content-types/restaurant/schema.json

{
  // ...
  {
    "attributes": {
      "pseudo": {
        "type": "string",
        "required": true
      },
      "email": {
        "type": "email",
        "required": true,
        "unique": true
      },
      "avatar": {
        "type": "media",
        "multiple": false,
      }
    }
  }
  // ...
}

In our second example, you can upload and attach multiple pictures to the restaurant.

// path: ./src/api/restaurant/content-types/restaurant/schema.json

{
  // ...
  {
    "attributes": {
      "name": {
        "type": "string",
        "required": true
      },
      "covers": {
        "type": "media",
        "multiple": true,
      }
    }
  }
  // ...
}

# Using a provider

By default Strapi provides a provider that uploads files to a local directory. You might want to upload your files to another provider like AWS S3.

Below are the providers maintained by the Strapi team:

You can also find additional community maintained providers on NPM (opens new window).

To install a new provider run:

# Local server

By default Strapi accepts localServer configurations for locally uploaded files. They will be passed as the options for koa-static (opens new window).

You can provide them by create or edit the file at ./config/plugins.js. The example below set max-age header.

# Enabling the provider

To enable the provider, create or edit the file at ./config/plugins.js

✏️ NOTE

When using community providers, pass the full package name to the provider key (e.g. provider: 'strapi-provider-upload-google-cloud-storage'). Only Strapi-maintained providers can use the shortcode format (e.g. provider: 'aws-s3').

Make sure to read the provider's README to know what are the possible parameters.

✋ CAUTION

Strapi has a default Security Middleware that has a very strict contentSecurityPolicy that limits loading images and media to "'self'" only, see the example configuration on the provider page or take a look at our middleware documentation for more information.

# Configuration per environment

When configuring your upload provider you might want to change the configuration based on the NODE_ENV environment variable or use environment specific credentials.

You can set a specific configuration in the ./config/env/{env}/plugins.js configuration file and it will be used to overwrite the one in the default configuration.

# Create providers

You can create a Node.js module to implement a custom provider. Read the official documentation here (opens new window).

Your provider needs to export the following interface:

💡 TIP

For performance reasons, the upload plugin will only use the uploadStream function if it exists, otherwise it will fallback on the upload function.

You can then publish it to make it available to the community.

# Create a local provider

If you want to create your own provider without publishing it on npm you can follow these steps:

  1. Create a ./providers/upload-{provider-name} folder in your root application folder.
  2. Create your provider as explained in the documentation above.
  3. Update your package.json to link your upload-{provider-name} dependency to point to the local path (opens new window) of your provider:
// path: ./package.json

{
  ...
  "dependencies": {
    ...
    "@strapi/provider-upload-{provider-name}": "file:providers/upload-{provider-name}"
    ...
  }
}
  1. Update the Upload plugin configuration:
  1. Run yarn install or npm install to install your new custom provider.