Docs

Resumable Upload

The Resumable Upload feature lets you resume an upload operation after network interruption or other transmission failure, saving time and bandwidth in the event of network failures.

It is especially useful in any of the following cases:

  • You are transferring larges files.
  • The probability of a network interruption is high.
  • Uploads are originating from a device with a low-bandwidth connection, such as a mobile phone.

This page explains the sequence of HTTP requests required to upload files using the resumable upload process.

If you don't want to implement this part on your own, feel free to check our SDKs instead. It'll make the process a whole lot easier for you.

1. Sending metadata

The first step required to use the Resumable Upload protocol is to send a POST request to the following URL. This first step will let us send file metadata, such as the desired filename, its description ...

POST /files

Request Headers

The following request headers must be set.

Content-Type: application/json; charset=utf-8
X-Upload-Content-Length => 9999,
X-Upload-Content-Type => application/octet-stream
X-Api-Key: your_api_key
  • X-Upload-Content-Length defines the number of bytes that will be uploaded in subsequent requests. Its value must be equal to the size of the file you are uploading.
  • X-Upload-Content-Type defines the MIME type of the file that you are uploading. It can also be set to application/octet-stream by default.

Request Body

Then, here is the request body. That's where you are able to specify file metadata.

{
    "filename": "your_file.exe",
    "description": "Hello world.",
    "visibility": "public"
}

Response

If the request succeeds, the API will respond with a 201 Created status code, and the response will include a Location header that specifies the URL for the resumable upload endpoint. This is the URL that you will use to upload the actual file (in other words, its content).

Location: {uploadUrl}

2. Sending the actual file

After receiving the resumable upload URL from the previous request, you will then need to upload the actual file contents by sending a PUT request to that specific location.

PUT {uploadUrl}

Request Headers

The following request headers must be set.

Content-Length: 9999
Content-Type: application/octet-stream
X-Api-Key: your_api_key
  • Content-Length defines the size of the file that you are uploading. Its value should be the same as the value of the X-Upload-Content-Length request header used in the previous request.
  • Content-Type defines the MIME type of the file that you are uploading. Its value must be the same as the value of the X-Upload-Content-Type request header used in the previous request.

Request Body

The body of the request is the actual file content.

Response

The request can lead to one of the following responses:

  • The file has been uploaded successfully.

If the request succeeds, the API will respond with a 201 Created status code, and the response will include a Location header that specifies the file URL. This means that the upload is complete and successful.

  • The upload did not succeed, but it can be resumed.

If the connection between the API and your application is lost, you should be able to resume the upload process by following the instructions for 2.1. Checking upload's status and 2.2. How to resume an upload below.

  • The upload did not succeed and it cannot be resumed.

The API may respond with an error message. This message helps to explain the cause of the failure. There are several cases of failure. It could also be due to the fact that your upload URL has expired.

2.1. Checking upload's status

If you want to check the status of a resumable upload, just send a PUT request to the upload URL that you received in 2. Sending the actual file.

PUT {uploadUrl}

Request Headers

In your request, set the Content-Range header value to bytes */{contentLength}, where {contentLength} is the total size of the file you are uploading.

Content-Length: 0
Content-Range : bytes */{contentLength}
X-Api-Key: your_api_key

Request Response

If the upload is already completed, the API will return the same response that it sent when the upload originally completed.

Otherwise, if the upload was interrupted or is still in progress, the response will have an 308 Resume Incomplete status code. In this response, the Range header specifies how many bytes of the file have already been successfully uploaded.

Here is an example:

308 Resume Incomplete
Content-Length: 0
Range: bytes=0-9999

Here, the Range header value is indexed from 0. This means that the first 10,000 bytes of the file have already been uploaded.

2.2 How to resume an upload

To resume an upload, you will need to send a PUT request to the upload URL received in 2. Sending the actual file.

PUT {uploadUrl}

Request Headers

Content-Length: {remainingContentLength}
Content-Range: bytes {firstByte}-{lastByte}/{contentLength}
X-Api-Key: your_api_key
  • Content-Length defines the size (in bytes) of the content that has not yet been uploaded.
  • Content-Range defines the portion of the file that you are uploading. The header value contains three very specific numbers:
    • {firstByte} The 0-based numeric index of the byte number from which you are resuming the upload. Its value is one number higher than the second number in the Range header retrieved in the previous step. In the previous example, the Range header value was 0-9999, so the first byte in a subsequent resumed upload request would be 10000.
    • {lastByte} The 0-based numeric index of the last byte of the binary file that you are uploading. Thus, it can be the last byte in the file. This means that if the file size was 50000 bytes, the last byte in the file would be 49999.
    • {contentLength} The total size of the file in bytes. Its value is the same as the X-Upload-Content-Length header specified in the first upload request.

Request Body

Set the request body to the binary code for the portion of the file that has not yet been uploaded. The portion is defined in the request headers above.

Sending file in chunks

Instead of trying to upload an entire file and resuming the upload in event of a network interruption, your application can break the file into chunks and send a series of requests to upload the chunks in sequence.

The instructions for uploading a file in chunks are identical to the process explained above (2.2 How to resume an upload). However, the requests to start uploading a file (2. Sending the actual file) and to resume an upload (2.2 How to resume an upload) both set the Content-Length and Content-Range header values differently when a file is being uploaded in chunks.

Request Headers

Content-Length: 10000
Content-Type: application/octet-stream
Content-Range: bytes 0-9999/1000000
X-Api-Key: your_api_key
  • The Content-Length header value specifies the size of the chunk that the request is sending.
  • The Content-Range header specifies the bytes in the file that the request is uploading. The instructions for setting the Content-Range header in 2.2. How to resume an upload are applicable when setting this value.

    Based on the example above, a value of bytes 0-9999/1000000 shows that the request is sending the first 10,000 bytes in a 1,000,000 byte file.

Request Body

Set the request body to the binary code for the portion of the file that you are uploading.

Response

The request can lead to one of the following responses:

  • The entire file has been uploaded. The API responds with a 201 Created status code and returns the file URL in the Location header.
  • Alternatively, if the request other than the final succeeds, the API responds with a 308 Resume Incomplete status code. The response format is the same as the one described in 2.2 How to resume an upload above.

    Then, just use the upper value returned in the response's Range header to determine where to start the next chunk.