# 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 parser middleware configuration in config/middleware.js:

module.exports = {
  //...
  settings: {
    parser: {
      enabled: true,
      multipart: true,
      formidable: {
        maxFileSize: 200 * 1024 * 1024 // Defaults to 200mb
      }
    }
  },
  //...
};

# 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:

module.exports = {
  upload: {
    breakpoints: {
      xlarge: 1920,
      large: 1000,
      medium: 750,
      small: 500,
      xsmall: 64
    }
  }
}

鉁 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 /upload/files Get a list of files
GET /upload/files/:id Get a specific file
POST /upload Upload files
DELETE /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 name 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:

"attributes": {
  "name": {
    "type": "string"
  },
  "cover": {
    "model": "file",
    "via": "related",
    "plugin": "upload"
  }
}

Code

<form>
  <!-- Can be multiple files if you setup "collection" instead of "model" -->
  <input type="file" name="files" />
  <input type="text" name="ref" value="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:

"attributes": {
  "name": {
    "type": "string"
  },
  "cover": {
    "model": "file",
    "via": "related",
    "plugin": "upload"
  }
}

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 鈥 User.settings.json.

{
  "connection": "default",
  "attributes": {
    "pseudo": {
      "type": "string",
      "required": true
    },
    "email": {
      "type": "email",
      "required": true,
      "unique": true
    },
    "avatar": {
      "model": "file",
      "via": "related",
      "plugin": "upload"
    }
  }
}

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

Path 鈥 Restaurant.settings.json.

{
  "connection": "default",
  "attributes": {
    "name": {
      "type": "string",
      "required": true
    },
    "convers": {
      "collection": "file",
      "via": "related",
      "plugin": "upload"
    }
  }
}

# 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.

You can check all the available providers developed by the community on npmjs.org - Providers list (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.

module.exports = ({ env })=>({
  upload: {
    providerOptions: {
      localServer: {
        maxage: 300000
      }
    }
  }
});

# Using scoped packages as providers

If your package name is scoped (opens new window) (for example @username/strapi-provider-upload-aws2) you need to take an extra step by aliasing it in package.json. Go to the dependencies section and change the provider line to look like this:

"strapi-provider-upload-aws2": "npm:@username/strapi-provider-upload-aws2@0.1.9"

The string after the last @ represents your desired semver (opens new window) version range.

# Enabling the provider

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

module.exports = ({ env }) => ({
  upload: {
    provider: 'aws-s3',
    providerOptions: {
      accessKeyId: env('AWS_ACCESS_KEY_ID'),
      secretAccessKey: env('AWS_ACCESS_SECRET'),
      region: 'aws-region',
      params: {
        Bucket: 'my-bucket',
      },
    },
  },
});

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

# 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).

To work with strapi, your provider name must match the pattern strapi-provider-upload-{provider-name}.

Your provider need to export the following interface:

module.exports = {
  init(providerOptions) {
    // init your provider if necessary

    return {
      upload(file) {
        // upload the file in the provider
      },
      delete(file) {
        // delete the file in the provider
      },
    };
  },
};

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:

  • Create a ./providers/strapi-provider-upload-{provider-name} folder in your root application folder.
  • Create your provider as explained in the documentation above.
  • Then update your package.json to link your strapi-provider-upload-{provider-name} dependency to point to the local path (opens new window) of your provider.
{
  ...
  "dependencies": {
    ...
    "strapi-provider-upload-{provider-name}": "file:providers/strapi-provider-upload-{provider-name}"
    ...
  }
}
  • Finally, run yarn install or npm install to install your new custom provider.