Uploading and downloading of components in the ftrack.server location is handled separately from the rest of the API.

Uploading files

Uploading files is done in three steps.

  1. A signed PUT URL is fetched from the server.
  2. The returned URL and headers is used to upload the file.
  3. The upload is finished by adding the component to the ftrack.server location.

Obtaining PUT Metadata

Issue an Get upload metadata operation to retrieve the PUT metadata to use.

Uploading the file

Example call using CURL:

curl -X PUT \
 --header "Content-Type: image/jpeg" \
 --header "Content-Disposition: attachment; filename=\"image.png\"" \
 --upload-file image.png \
 

The response may vary depending on which media server is used, but you can assume that a HTTP response of 200 indicates that the upload was successful.

Finalizing the upload

After the file has been uploaded, it should be marked as present in the ftrack server location. This can be done with a call to the API endpoint, creating a ComponentLocation. It can now also be used for various other operations such as adding it to a version, encode it to a reviewable format or adding as a thumbnail.

Example request body:

[
  {
    "action": "create",
    "entity_type": "ComponentLocation",
    "entity_data": {
      "location_id": "3a372bde-05bc-11e4-8908-20c9d081909b",
      "component_id":
    }
  }
]

Computing the checksum

The checksum is used as the Content-MD5 header and should contain the base64-encoded 128-bit MD5 digest of the message (without the headers) according to RFC 1864. This can be used as a message integrity check to verify that the data is the same data that was originally sent. Although it is optional, we recommend using the checksum mechanism as an end-to-end integrity check.

For reference, this is the implementation in the python client.

def _compute_checksum(fp):
    '''Return checksum for file.'''
    buf_size = 8192
    hash_obj = hashlib.md5()
    spos = fp.tell()    s = fp.read(buf_size)
    while s:
        hash_obj.update(s)
        s = fp.read(buf_size)    base64_digest = base64.encodestring(hash_obj.digest())
    if base64_digest[-1] == '\n':
        base64_digest = base64_digest[0:-1]    fp.seek(spos)
    return base64_digest
Did this answer your question?