To upload data files more reliably, you can use the resumable upload protocol. This protocol allows you to resume an upload operation after a communication failure has interrupted the flow of data. It is especially useful if you are transferring large files and the likelihood of a network interruption or some other transmission failure is high, for example, when uploading from a mobile client app. It can also reduce your bandwidth usage in the event of network failures because you don't have to restart large file uploads from the beginning.
The steps for using resumable upload include:
In addition, apps that use resumable upload need to have code to resume an interrupted upload. If an upload is interrupted, find out how much data was successfully received, and then resume the upload starting from that point.
For this initiating request, the body is either empty or it contains the metadata only; you'll transfer the actual contents of the file you want to upload in subsequent requests.
Use the following HTTP headers with the initial request:
X-Upload-Content-Type
. Set to the media MIME type of the upload data to be transferred in subsequent requests.X-Upload-Content-Length
. Set to the number of bytes of upload data to be transferred in subsequent requests.Content-Type
. Set according to the metadata's data type.Content-Length
. Set to the number of bytes provided in the body of this initial request.The following example shows the use of a resumable upload request for an upload path that would be /upload
:
POST /upload?uploadType=resumable HTTP/1.1 Host: www.example.com Content-Length: 41 Content-Type: application/json; charset=UTF-8 X-Upload-Content-Type: image/jpeg X-Upload-Content-Length: 2000000 { "name": "Some value" }
If the session initiation request succeeds, the API server responds with a 200 OK
HTTP status code. In addition, it provides a Location
header that specifies your resumable session URI. The Location
header, shown in the example below, includes an uploadId
query parameter portion that gives the unique upload ID to use for this session.
Here is the response to the request in the last step:
HTTP/1.1 200 OK Location: /upload?uploadType=resumable&uploadId=fooBar123 Content-Length: 0
The value of the Location
header, as shown in the above example response, is the session URI you'll use as the HTTP endpoint for doing the actual file upload or querying the upload status.
To upload the file, send a PUT
request to the upload URI that you obtained in the previous step.
The HTTP headers to use when making the resumable file upload requests includes Content-Length
. Set this to the number of bytes you are uploading in this request, which is generally the upload file size.
PUT /upload?uploadType=resumable&uploadId=fooBar123 HTTP/1.1 Content-Length: 2000000 Content-Type: image/jpeg bytes 0-1999999
If the request succeeds, the server responds with an HTTP 201 Created
, along with any metadata associated with this resource. If the initial request of the resumable session had been a PUT
, to update an existing resource, the success response would be 200 OK
, along with any metadata associated with this resource.
With resumable uploads, you can break a file into chunks and send a series of requests to upload each chunk in sequence. This is not the preferred approach since there are performance costs associated with the additional requests, and it is generally not needed. However, you might need to use chunking to reduce the amount of data transferred in any single request.
If you are uploading the data in chunks, the Content-Range
header is also required, along with the Content-Length
header required for full file uploads:
Content-Length
. Set to the chunk size or possibly less, as might be the case for the last request.Content-Range
: Set to show which bytes in the file you are uploading. For example, Content-Range: bytes 0-524287/2000000
shows that you are providing the first 524,288 bytes in a 2,000,000 byte file.A sample request would be:
PUT {session_uri} HTTP/1.1 Host: www.example.com Content-Length: 524288 Content-Type: image/jpeg Content-Range: bytes 0-524287/2000000 bytes 0-524288
If the request succeeds, the server responds with 308 Resume Incomplete
, along with a Range
header that identifies the total number of bytes that have been stored so far:
HTTP/1.1 308 Resume Incomplete Content-Length: 0 Range: 0-524287
Use the upper value returned in the Range
header to determine where to start the next chunk. Continue to PUT each chunk of the file until the entire file has been uploaded
If an upload request is terminated before receiving a response or if you receive an HTTP 503 Service Unavailable
or even an HTTP 500 Internal Server Error
response from the server, then you need to resume the interrupted upload. To do this:
Request the upload status
PUT {session_uri} HTTP/1.1 Content-Length: 0 Content-Range: bytes */2000000
Extract the number of bytes uploaded so far from the response
The server's response uses the Range
header to indicate that it has received the first 43 bytes of the file so far. Use the upper value of the Range
header to determine where to start the resumed upload.
HTTP/1.1 308 Resume Incomplete Content-Length: 0 Range: 0-42
Resume the upload from the point where it left off
Use the upload file in chunks method to restart upload at the point where there's a failure.