# Initiates a direct external upload

`POST /uploads/generate-presigned-put.json`

Direct external uploads bypass the usual method of creating uploads
via the POST /uploads route, and upload directly to an external provider,
which by default is S3. This route begins the process, and will return
a unique identifier for the external upload as well as a presigned URL
which is where the file binary blob should be uploaded to.

Once the upload is complete to the external service, you must call the
POST /complete-external-upload route using the unique identifier returned
by this route, which will create any required Upload record in the Discourse
database and also move file from its temporary location to the final
destination in the external storage service.

You must have the correct permissions and CORS settings configured in your
external provider. We support AWS S3 as the default. See:

https://meta.discourse.org/t/-/210469#s3-multipart-direct-uploads-4.

An external file store must be set up and `enable_direct_s3_uploads` must
be set to true for this endpoint to function.



Authentication: no security requirement declared for this operation.

Request body: application/json

Type: any

- `type` (required)
  Type: string
  
  enum: ["avatar","profile_background","card_background","custom_emoji","composer"]

- `file_name` (required)
  Type: string
  
  Example:
  
  ```json
  "IMG_2021.jpeg"
  ```

- `file_size` (required)
  Type: integer
  
  File size should be represented in bytes.
  
  Example:
  
  ```json
  4096
  ```

- `metadata` (optional)
  Type: object
  
  - `sha1-checksum` (optional)
    Type: string
    
    The SHA1 checksum of the upload binary blob. Optionally
    be provided and serves as an additional security check when
    later processing the file in complete-external-upload endpoint.
  
  Additional properties: false

Additional properties: false

Responses:

- 200: external upload initialized

Content type: application/json

Type: any

- `key` (optional)
  Type: string
  
  The path of the temporary file on the external storage
  service.
  
  Example:
  
  ```json
  "temp/site/uploads/default/12345/67890.jpg"
  ```

- `url` (optional)
  Type: string
  
  A presigned PUT URL which must be used to upload
  the file binary blob to.
  
  Example:
  
  ```json
  "https://file-uploads.s3.us-west-2.amazonaws.com/temp/site/uploads/default/123/456.jpg?x-amz-acl=private&x-amz-meta-sha1-checksum=sha1&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AAAAus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20211221T011246Z&X-Amz-Expires=600&X-Amz-SignedHeaders=host&X-Amz-Signature=12345678"
  ```

- `signed_headers` (optional)
  Type: object
  
  A map of headers that must be sent with the PUT request.
  
  Example:
  
  ```json
  {
    "x-amz-acl": "private",
    "x-amz-meta-sha1-checksum": "sha1"
  }
  ```

- `unique_identifier` (optional)
  Type: string
  
  A unique string that identifies the external upload.
  This must be stored and then sent in the /complete-external-upload
  endpoint to complete the direct upload.
  
  Example:
  
  ```json
  "66e86218-80d9-4bda-b4d5-2b6def968705"
  ```

Additional properties: false

## Examples

### cURL

```bash
curl -X POST 'https://discourse.example.com/uploads/generate-presigned-put.json' \
  -H 'Content-Type: application/json' \
  --data-raw '{
  "type": "avatar",
  "file_name": "IMG_2021.jpeg",
  "file_size": 4096,
  "metadata": {
    "sha1-checksum": "string"
  }
}'
```

### JavaScript

```javascript
const body = `{
  "type": "avatar",
  "file_name": "IMG_2021.jpeg",
  "file_size": 4096,
  "metadata": {
    "sha1-checksum": "string"
  }
}`;

const response = await fetch('https://discourse.example.com/uploads/generate-presigned-put.json', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body,
});

const data = await response.text();
```

### Python

```python
import requests

body = '''{
  "type": "avatar",
  "file_name": "IMG_2021.jpeg",
  "file_size": 4096,
  "metadata": {
    "sha1-checksum": "string"
  }
}'''

response = requests.post(
    'https://discourse.example.com/uploads/generate-presigned-put.json',
    data=body.encode('utf-8'),
    headers={
        'Content-Type': 'application/json',
    },
)
print(response.text)
```
