2019-10-07 16:02:15 +02:00
# Upload
2019-05-06 16:17:16 +02:00
2020-03-22 13:28:03 -04:00
Thanks to the plugin `Upload` , you can upload any kind of file on your server or external providers such as **AWS S3** .
2019-10-07 16:02:15 +02:00
2020-04-16 10:04:36 +02:00
## Configuration
Currently the strapi middleware in charge of parsing request needs to be configured to support bigger file sizes if you need to upload file with a size greater than 200MB.
The library we use is [`koa-body` ](https://github.com/dlau/koa-body ), and itself uses the [`node-formidable` ](https://github.com/felixge/node-formidable ) library to process files.
You can pass configuration to the middleware directly by setting it in the `parser` middleware configuration:
```json
{
"parser": {
"enabled": true,
"multipart": true,
"formidable": {
"maxFileSize": 20000000 // defaults to 200mb
}
}
}
```
2019-10-07 16:02:15 +02:00
## Endpoints
< style lang = "stylus" >
#endpoint-table
table
display table
width 100%
tr
border none
& :nth-child(2n)
background-color white
tbody
tr
border-top 1px solid #dfe2e5
th, td
border none
padding 1.2em 1em
border-right 1px solid #dfe2e5
& :last-child
border-right none
< / style >
< div id = "endpoint-table" >
| 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 |
2019-05-06 16:17:16 +02:00
2019-10-07 16:02:15 +02:00
< / div >
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
## Upload files
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
To upload files into your application.
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
### Parameters
2019-05-06 16:17:16 +02:00
- `files` : The file(s) to upload. The value(s) can be a Buffer or Stream.
2019-09-24 16:22:22 +02:00
### Code example
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
```html
< form >
<!-- Can be multiple files -->
< input type = "file" name = "files" / >
< input type = "submit" value = "Submit" / >
< / form >
2019-07-09 07:56:59 +09:00
2019-09-24 16:22:22 +02:00
< script type = "text/javascript" >
const formElement = document.querySelector('form');
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
formElement.addEventListener('submit', e => {
e.preventDefault();
2019-07-18 19:28:52 +02:00
2019-09-24 16:22:22 +02:00
const request = new XMLHttpRequest();
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
request.open('POST', '/upload');
2019-07-18 19:28:52 +02:00
2019-09-24 16:22:22 +02:00
request.send(new FormData(formElement));
});
< / script >
2019-05-06 16:17:16 +02:00
```
2019-09-24 16:22:22 +02:00
::: warning
You have to send FormData in your request body
:::
## Upload files related to an entry
2020-03-22 13:28:03 -04:00
To upload files that will be linked to a specific entry.
2019-09-24 16:22:22 +02:00
### Request parameters
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
- `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
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
The `Restaurant` model attributes:
2019-05-06 16:17:16 +02:00
```json
"attributes": {
2019-09-24 16:22:22 +02:00
"name": {
2019-05-06 16:17:16 +02:00
"type": "string"
},
"cover": {
"model": "file",
"via": "related",
2019-09-24 16:22:22 +02:00
"plugin": "upload"
2019-05-06 16:17:16 +02:00
}
}
```
2019-09-24 16:22:22 +02:00
Code
2019-05-06 16:17:16 +02:00
```html
< form >
2019-09-24 16:22:22 +02:00
<!-- Can be multiple files if you setup "collection" instead of "model" -->
2019-07-18 19:28:52 +02:00
< input type = "file" name = "files" / >
2019-09-24 16:22:22 +02:00
< input type = "text" name = "ref" value = "restaurant" / >
2019-07-18 19:28:52 +02:00
< input type = "text" name = "refId" value = "5c126648c7415f0c0ef1bccd" / >
< input type = "text" name = "field" value = "cover" / >
< input type = "submit" value = "Submit" / >
2019-05-06 16:17:16 +02:00
< / form >
< script type = "text/javascript" >
const formElement = document.querySelector('form');
2019-07-18 19:28:52 +02:00
formElement.addEventListener('submit', e => {
2019-05-06 16:17:16 +02:00
e.preventDefault();
const request = new XMLHttpRequest();
request.open('POST', '/upload');
request.send(new FormData(formElement));
});
< / script >
```
2019-09-24 16:22:22 +02:00
::: warning
You have to send FormData in your request body
:::
## Upload file during entry creation
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
You can also add files during your entry creation.
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
### Examples
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
The `Restaurant` model attributes:
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
```json
"attributes": {
"name": {
"type": "string"
},
"cover": {
"model": "file",
"via": "related",
"plugin": "upload"
}
}
2019-05-06 16:17:16 +02:00
```
2019-09-24 16:22:22 +02:00
Code
```html
< 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') {
if (currentElement.files.length === 1) {
const file = currentElement.files[0];
formData.append(`files.${currentElement.name}` , file, file.name);
} else {
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 >
2019-05-06 16:17:16 +02:00
```
2020-03-22 13:28:03 -04:00
Your entry data has to be contained in a `data` key. You have to `JSON.stringify` your data object.
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
And for your files, they have to be prefixed by `files` .
Example here with cover attribute `files.cover` .
2019-11-07 12:05:39 +01:00
::: tip
2020-03-22 13:28:03 -04:00
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.
2019-12-09 14:38:19 +01:00
Example `files.my_component_name[the_index].attribute_name`
2019-09-24 16:22:22 +02:00
:::
::: warning
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` .
2019-05-06 16:17:16 +02:00
```json
{
"connection": "default",
"attributes": {
"pseudo": {
"type": "string",
"required": true
},
"email": {
"type": "email",
"required": true,
"unique": true
},
"avatar": {
"model": "file",
"via": "related",
"plugin": "upload"
}
}
}
```
2019-09-24 16:22:22 +02:00
In our second example, you can upload and attach multiple pictures to the restaurant.
2019-05-06 16:17:16 +02:00
2019-09-24 16:22:22 +02:00
**Path —** `Restaurant.settings.json` .
2019-07-18 19:28:52 +02:00
2019-09-24 16:22:22 +02:00
```json
{
"connection": "default",
"attributes": {
"name": {
"type": "string",
"required": true
},
"convers": {
"collection": "file",
"via": "related",
"plugin": "upload"
}
}
}
2019-05-06 16:17:16 +02:00
```
2020-02-27 19:34:14 +01:00
## Using a provider
2019-05-06 16:17:16 +02:00
2020-04-10 15:51:35 +02:00
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.
2019-05-06 16:17:16 +02:00
You can check all the available providers developed by the community on npmjs.org - [Providers list ](https://www.npmjs.com/search?q=strapi-provider-upload- )
To install a new provider run:
```
2020-02-27 19:34:14 +01:00
$ npm install strapi-provider-upload-aws-s3 --save
2019-05-06 16:17:16 +02:00
```
2020-02-27 19:34:14 +01:00
or
```
$ yarn add strapi-provider-upload-aws-s3
```
2019-05-06 16:17:16 +02:00
2020-02-27 19:34:14 +01:00
To enable the provider, create or edit the file at `./extensions/upload/config/settings.json`
```json
{
"provider": "aws-s3",
"providerOptions": {
"accessKeyId": "dev-key",
"secretAccessKey": "dev-secret",
"region": "aws-region",
"params": {
"Bucket": "my-bucket"
}
}
}
```
Make sure to read the provider's `README` to know what are the possible parameters.
2019-05-06 16:17:16 +02:00
2020-04-21 14:58:02 +02:00
### Configuration per envrionment
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 do so using a `settings.js` file:
```js
if (process.env.NODE_ENV === 'production') {
module.exports = {
provider: 'providerName',
providerOptions: {
cloud_name: process.env.PROVIDER_CLOUD_NAME,
api_key: process.env.PROVIDER_API_KEY,
api_secret: process.env.PROVIDER_API_SECRET,
},
};
} else {
// to use the default local provider you can return an empty configuration
module.exports = {};
}
```
2020-02-11 02:28:28 -07:00
2019-05-06 16:17:16 +02:00
## Create providers
2020-02-27 19:34:14 +01:00
You can create a Node.js module to implement a custom provider. Read the official documentation [here ](https://docs.npmjs.com/creating-node-js-modules ).
To work with strapi, your provider name must match the pattern `strapi-provider-upload-{provider-name}` .
Your provider need to export the following interface:
```js
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
},
};
},
};
```
2019-10-23 10:51:51 +02:00
2020-02-27 19:34:14 +01:00
You can then publish it to make it available to the community.
2019-10-23 10:51:51 +02:00
### Create a local provider
2019-10-24 15:14:05 +02:00
If you want to create your own provider without publishing it on **npm** you can follow these steps:
2019-10-23 10:51:51 +02:00
2020-02-27 19:34:14 +01:00
- Create a `./providers/strapi-provider-upload-{provider-name}` folder in your root application folder.
- Create your provider as explained in the [documentation ](#create-providers ) above.
- Then update your `package.json` to link your `strapi-provider-upload-{provider-name}` dependency to point to the [local path ](https://docs.npmjs.com/files/package.json#local-paths ) of your provider.
2019-10-23 10:51:51 +02:00
```json
{
...
"dependencies": {
...
2020-02-27 19:34:14 +01:00
"strapi-provider-upload-{provider-name}": "file:providers/strapi-provider-upload-{provider-name}"
2019-10-23 10:51:51 +02:00
...
}
}
```
- Finally, run `yarn install` or `npm install` to install your new custom provider.