File Upload

Contents

In order to make file uploading as easy and flexible as possible we support several scenarios for this procedure.

Two-step upload

With Files API you can first upload files separately and then "attach" them to appropriate resources.

Resources, that support this scenario, declare special File resource handling fields, that end with _file_id (for single file) or with _file_ids (for multiple files).

With this scenario you can also re-use uploaded files (i.e. "attach" the same file to different resources).

Upload to File resource

During the first step you upload files to the File resource using the POST HTTP method as described here.

POST /api/v1/files.json HTTP/1.1
Host: brewfictus.kayako.com
Content-Disposition: attachment; filename="coffee.png"
Content-Length: 2347
Content-Type: image/png

...

This is, in fact, the single-step upload to the File resource.

Associate file with resource

For each uploaded file Files API generates unique ID, that can be used to associate the file with a resource during the second step. To do this pass the ID as a value for a resource's file handling field.

PUT /api/v1/profile.json HTTP/1.1
Host: brewfictus.kayako.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 17

avatar_file_id=19

Single-step upload

The single-step upload technique is used to upload files to resources directly.

Upload file content as request body

This is the simplest uploading technique from the low-level technical perspective.

To upload a file you can just pass its contents as the request body.

File name

To specify the name of the uploaded file (required in most cases) use the Content-Desposition HTTP header:

POST /api/v1/files.json HTTP/1.1
Host: brewfictus.kayako.com
Content-Disposition: attachment; filename="coffee.png"

Alternatively, you can use the _filename argument:

/api/v1/files.json?_filename=coffee.png

Field name

If the API end point expects a field name for the uploaded file (e.g. if multiple target fields are supported) use the Content-Desposition HTTP header as follows:

POST /api/v1/files.json HTTP/1.1
Host: brewfictus.kayako.com
Content-Disposition: attachment; name="avatar"; filename="coffee.png"

Alternatively, you can use the _field argument:

/api/v1/files.json?_field=avatar&_filename=coffee.png

File size

We strongly recommend to always specify the file size in the Content-Length HTTP header of the request.

POST /api/v1/files.json HTTP/1.1
Host: brewfictus.kayako.com
Content-Length: 2347

This way you also ensure that an incomplete file won't be accepted by the server.

Checksum

To ensure, that content of the file was not damaged during the network transfer include the Content-MD5 header with the MD5 hash of the file into your request:

POST /api/v1/files.json HTTP/1.1
Host: brewfictus.kayako.com
Content-MD5: f9e590b40fe31ecd4e0c4fc3f3c0b9fd

Alternatively, you can use the _md5 argument:

/api/v1/files.json?_md5=f9e590b40fe31ecd4e0c4fc3f3c0b9fd

Complete example

Here is the complete example of the request headers, which can be used for uploading files using this technique:

POST /api/v1/files.json HTTP/1.1
Host: brewfictus.kayako.com
Content-Disposition: attachment; name="avatar"; filename="coffee.png"
Content-MD5: f9e590b40fe31ecd4e0c4fc3f3c0b9fd
Content-Length: 2347
Content-Type: image/png

...
CURL

Here is the example of the CURL command used for uploading files with this technique.

curl -X POST \
     -H 'Content-Type: image/png' \
     -d @coffee.png 'https://brewfictus.kayako.com/api/v1/files.json?_filename=coffee.png'

By default CURL always adds Content-Type: application/x-www-form-urlencoded, what makes the API server think, that the body contains parameters. So, to upload files as the body always specify the Content-Type, e.g. application/octet-stream.

The special CURL file uploading mode is also supported:

curl -X POST \
     -T coffee.png 'https://brewfictus.kayako.com/api/v1/files.json?_filename=coffee.png'

Using multi-part form data

This is the most commonly used uploading technique, which is used by web browsers to upload files to HTTP servers by default. This is also the only technique, that allows to upload files and to send parameters in a single request body. Additionally, this technique can be used to upload multiple files at once.

This technique is identified by the Content-Type HTTP request header, which must be set to multipart/form-data.

POST /api/v1/files.json HTTP/1.1
Host: brewfictus.kayako.com
Content-Type: multipart/form-data; boundary="1modcYGLAATJpapo8jhD4UwHbF5asu4u"

Here, the boundary is a special unique string, that is used to split the request body into "parts".

The request body and each its part must start with the special line:

--<boundary>

The last line of the request body must be:

--<boundary>--

Like a HTTP request each part of the multi-part request must start with HTTP headers, that describe this part, following by an empty line and the contents.

The following HTTP headers are supported for parts of the multi-part request:

  • Content-Disposition is required and must be set to form-data. Additionally, it may include the name (field name) and the filename.
  • Content-Length is strongly recommended and must be set to the size of the content delivered inside the part.
  • Content-MD5 can be specified to ensure that data won't be saved in a damaged state.
  • Content-Type can be used to specify the MIME type of the file.
  • Content-Transfer-Encoding to specify encoding of the content. The binary encoding is recommended.

See also RFC 2388 for details.

Complete example

Here is the complete example of the request, that uses this format:

POST /api/v1/files.json HTTP/1.1
Host: brewfictus.kayako.com
Content-Type: multipart/form-data; boundary="1modcYGLAATJpapo8jhD4UwHbF5asu4u"

--1modcYGLAATJpapo8jhD4UwHbF5asu4u
Content-Disposition: form-data; filename="coffee.png"
Content-Type: image/png
Content-Transfer-Encoding: binary

...
--1modcYGLAATJpapo8jhD4UwHbF5asu4u
Content-Disposition: form-data; filename="cappuccino.png"
Content-Type: image/png
Content-Transfer-Encoding: binary

...
--1modcYGLAATJpapo8jhD4UwHbF5asu4u--
CURL

Here is the example of the CURL command, that uses this format:

curl -X POST \
     -F "files[]=@coffee.png" \
     -F "files[]=@cappuccino.png" 'https://brewfictus.kayako.com/api/v1/files.json'