Skip to main content

 

Documentation & User Guides | FotoWare

Uploading assets using the API

Applications and integrations can ingest assets into FotoWeb by using the upload API.

Assets can be added to archives either by copying or moving them from other archives or by uploading new files. The upload API also supports creating new folders and folder hierarchies and applying metadata to assets immediately upon ingestion.

Required permissions

Upload requires authentication.

  • If server-to-server authentication is used, then the client can upload assets at any location where upload is supported.
  • If the client is impersonating a specific user (e.g., when using user server-to-server API authentication), then that user must have upload permission on the upload location.

Request URL

Assets are uploaded by making a POST request to the URL of the collection to upload to. Each request can contain one or more assets.

It is also possible to create a new folder (or a hierarchy of nested folders) and upload assets to the new folder. This is done by adding all new folders to the end of the URL as follows:

POST upload_location_url/folder1/folder2/.../

where

Parameter

Description

upload_location_url URL of the collection (e.g., archive or folder) to upload to (upload location)
folder1folder2, ... (optional) Names of new folders to be created

Note:

  • New folders can only be created if the canCreateFolders flag is true for the collection assets are being uploaded to. For more information, see Ingestion.
  • The upload location URL (folder_url) must be the public URL of the collection, which is given in the href attribute in the JSON representation. Do NOT use the private URL given in the data attribute.

Which collections support uploading?

To determine the upload location (which is the request URL of the upload request), you must first find a collection that supports upload.

Assets can only be uploaded to archives. Furthermore, assets can only be uploaded to certain locations within archives:

  • If the archive has a custom input folder, then assets can only be uploaded to the root URL of the archive. It is not possible to upload to a specific sub folder or to create a new sub folder during upload.
  • If the archive does not have a custom input folder, then assets can only be uploaded to physical folders. A physical folder is any sub folder that represents an actual folder on disk. For example, the root of an archive or the root of a union member is NOT a physical folder.

It is recommended to use the upload destination list API to discover possible upload locations and/r to check the properties of a particular collection to see if it is a valid upload location. For more information, see ingestion.

Request body

Upload uses HTTP Multipart requests, as defined in RFC1341 (external link).

Note:

You usually do not need to implement RFC1341 by yourself. Most likely, the HTTP client library of your programming platform which you use for sending HTTP requests has built-in support for HTTP multipart requests. This is the standard format for uploading files, so check if your HTTP client library has functions for attaching files to requests.

We provide example code some various programming languages and platforms, which can be found below.

Here is an example of a complete upload request for one file:

POST /fotoweb/archives/5000-Wirefeed/Incoming/
Accept: application/vnd.fotoware.upload-result+json
Content-Type: multipart/form-data; boundary=WUG7zDvyA3hVq16Q
authentication headers
 
--WUG7zDvyA3hVq16Q
Content-Disposition: form-data; name="Filedata"; filename="image.jpg"
Content-Type: image/jpeg
 
binary image data
--WUG7zDvyA3hVq16Q

 

where

Parameter

Description

boundary

Boundary between parts of the request. Can be chosen freely by the client. The string is the same for all parts of the request. It should be different for each request, random and long enough to minimize the chance that it occurs in the files being uploaded. HTTP client libraries usually take care of this. In the example above, "WUG7zDvyA3hVq16Q" was chosen as the boundary string. Note that the boundary string is preceded by two dashes (--) at the end of each part.
filename The filename that the asset will have in FotoWeb after uploading. Must be specified for each part of the request that contains a file. The filename can be chosen freely and does not need to be identical to the filename of the file on the local disk on the client. HTTP client library functions should expect this as a parameter.
Content-Type Ignored by FotoWeb. Should match the MIME type of the file, but can safely be set to application/octet-stream regardless of file type.

Notes:

  • All blank lines are required, and all line breaks that are part of the request body syntax must be in CRLF (carriage-return + line-feed; "\r\n") format.
  • The maximum file size of uploads is limited by the maximum size of requests to FotoWeb. This is currently 2 GB when using IIS and 4 GB when using Apache. Note that, when uploading multiple files in one request, the limit applies to the total size of the request, including headers and metadata. It is therefore recommended to upload assets in one request per asset if files may be large.

 

Response

If the upload request was successful, then the response status is 201 Created, and the Location header contains the URL of the first uploaded asset.

201 Created
Location: https://fotoweb.acme.com/fotoweb/archives/5000-Wirefeed/Incoming/image.jpg
Content-Type: application/vnd.fotoware.upload-result+json

 More information about all assets can be found in the JSON in the response body, which has the following format:

{
  "uploadedFiles": [
    {
      "asset": { "href": "/fotoweb/archives/5000-Wirefeed/Incoming/image.jpg", ... },
      "originalFilename": "image.jpg"
    },
    {...},
    ...
  ]
}

 where uploadedFiles is an array where each entry represents a single uploaded asset with the following attributes:

Parameter

Description

asset All information about the asset that was created. The format is the usual JSON representation of an asset.
originalFilename The filename that was given in the upload request

Notes:

  • If more than one file are uploaded, then the Location header only contains the URL of one asset that was created. In this case, it is necessary to look at the JSON response to get information about all assets.
  • The actual filename of the asset may differ from the filename parameter given in the request. FotoWeb will rename an uploaded asset if there already is an asset with the same name in the same location. The originalFilename attribute is always identical to what was given in the filename parameter in the request. The actual filename (after renaming) is available in asset.filename in the response. Example:
{
  "uploadedFiles": [
    {
      "asset": {
        "href": "/fotoweb/archives/5000-Wirefeed/Incoming/Image_1.jpg",
        "filename": "Image_1.jpg",  // Filename after renaming
        ...
      },
      "originalFilename": "Image.jpg"  // Filename given in request
    },
    ...
  ]
}
  • To make it possible to identify each uploaded asset in the response, a different, unique filename parameter must be given for each asset in the request.
  • Information about the assets is not available when uploading to an archive with a custom input folder. This is because FotoWeb does not know where the file will eventually end up. For example, the input folder of the archive might be the input folder of a ColorFactory channel, which processes and potentially moves the file. As a result of the processing, zero or more files may eventually end up in any FotoWeb archives.

Applying metadata during upload

Metadata can be applied to assets during upload. This ensures strong metadata consistency in FotoWeb archives. If a client uploaded assets and applied metadata later in a separate request, then these assets might be without metadata, without consistent metadata or without required metadata fields for a short period of time after the upload. Applying metadata during upload ensures that all assets in the FotoWeb systems always have fully consistent metadata.

Metadata can be applied to each asset in an upload request. This is done by adding a metadata part to the request body for each asset to which metadata shall be applied:

--WUG7zDvyA3hVq16Q
Content-Disposition: name="Metadata" filename="image.jpg.metadata.json"
 
{
  "fields": [
    {"id": 5, "value": "Roadrunner"},
    {"id": 80, "value": "Wyle E. Coyote", "action": "add"},
    {"id": 25, "action": "erase"},
    {"id": 25, "action": "add", "value": ["chicken", "food"]}
  ]
}

 where the Content-Disposition header parameter must be set as follows:

Parameter

Description

name Must always be "Metadata".
filename

Must be "FILENAME.EXT.metadata.json" where "FILENAME.EXT" is the filename of the file (including extension) as given in the filename parameter of the request and ".metadata.json" is a pseudo-extension that must always be the same.

For example, when applying metadata to an asset where filename is set to "image.jpg" in the "FileData" part, then the "Metadata" part must begin as follows:

--WUG7zDvyA3hVq16Q
Content-Disposition: name="Metadata" filename="image.jpg.metadata.json"

Metadata patch instructions

In the JSON body, fields is an array of metadata patch instructions where each instruction has the following parameters:

Parameter

Description

id

Numeric ID of the metadata field.

This parameter is required.

action

Metadata action to perform, as described below.

This parameter is optional. If omitted, the default action is "add".

value

Metadata value(s) to set or add.

This parameter is optional or required, depending on the action, as described below.

Depending on the action and field type, this can be a single value (given as a string) or zero or multiple values (given as an array of strings).

The action parameter defines what the metadata patch instruction does:

Action

Description

"add"

Set the field to the given value or values.

If the field already has a value, and the field is a bag field, then the value is added to the existing values of the field.

The value parameter is required. If the field is a bag field, then either a single value or multiple values may be given. Otherwise, at most one value may be given (either as a string or as an array containing a single string element). If an empty array is given, then this action does nothing.

Example:

// If the field is a non-bag field:
"value": "foo"           // Replaces existing value with "foo"
"value": ["foo"]         // Replaces existing value with "foo"
"value": []              // valid, but does nothing
"value": ["foo", "bar"]  // INVALID, because at most one value may be given


// If the field is a bag field:
"value": "foo"           // Adds "foo" to existing values
"value": ["foo"]         // Adds "foo" to existing values
"value": ["foo", "bar"]  // Adds "foo" and "bar" to existing values
"value": []              // valid, but does nothing
"append"

Append the given value to the existing value of the field. If the field does not have a value, then this action is equivalent to "add".

If the field is a bag field, then the given value is appended to the first value of the existing array of values of the field.

The value parameter is required and must be a string containing a single value.

"prepend"

Prepend the given value to the existing value of the field. If the field does not have a value, then this action is equivalent to "add".

If the field is a bag field, then the given value is prepended to the first value of the existing array of values of the field.

The value parameter is required and must be a string containing a single value.

"erase"

Remove the given field from the metadata.

If the field is a bag field, then all values in the bag are removed.

 

Example: Applying metadata to non-bag fields

The following metadata patch instructions:

{
  "fields": [
    {"id": 500, "value": "V1"},
    {"id": 501, "action": "erase"},
    {"id": 502, "action": "append", "value": "V3"},
    {"id": 503, "action": "prepend", "value": "V4"}
  ]
}

modifies the following existing metadata as follows:

Field

Existing value

Final value

500 E1 V1
501 E2 (empty)
502 E3 E3V3
503 E4 V4E4

 

Example: Applying metadata to a bag field

The following metadata patch instructions:

{
  "fields": [
    {"id": 25, "action": "erase"},
    {"id": 25, "action": "add", "value": ["food", "chicken"]},
    {"id": 80, "action": "add", "value": "Wyle E. Coyote"}
  ]
}

modifies the following existing metadata as follows:

Field

Existing values

Final values

25

foo

bar

food

chicken

80 Roadrunner

Roadrunner

Wyle E. Coyote

Note: ​ To replace all values in a bag field with new values, use the "erase" action before adding new values with the add action.

Metadata fields that are automatically set

When uploading assets to FotoWeb, FotoWeb sets certain fields automatically. This is described here.

Full example

The following is an example of a complete upload request with metadata:

POST /fotoweb/archives/5000-Wirefeed/Incoming/
Accept: application/vnd.fotoware.upload-result+json
Content-Type: multipart/form-data; boundary=WUG7zDvyA3hVq16Q
authentication headers
 
--WUG7zDvyA3hVq16Q
Content-Disposition: form-data; name="Filedata"; filename="image.jpg"
Content-Type: image/jpeg
 
binary image data
--WUG7zDvyA3hVq16Q
Content-Disposition: name="Metadata" filename="image.jpg.metadata.json"
 
{
  "fields": [
    {"id": 5, "value": "Roadrunner"},
    {"id": 80, "value": "Wyle E. Coyote", "action": "add"},
    {"id": 25, "action": "erase"},
    {"id": 25, "action": "add", "value": ["chicken", "food"]}
  ]
}
--WUG7zDvyA3hVq16Q

Upload example using cURL

The following command uploads two files to an archive which has a custom input folder:

curl --header "FWAPIToken: 12345" \
-F "image=@/Users/<User Name>/Desktop/file1.JPG" \
-F "image=@/Users/<User Name>/Desktop/file2.pdf" \
http://fotoweb.fotoware.com/fotoweb/archives/5004-Uploads/

Note that this command automatically creates a HTTP multipart request according to RFC1341 simply because the cURL parameter -F is used, which attaches a file to the request. This is an example of how HTTP clients implement RFC1341 and it isn't necessary to craft such requests by hand.

Upload example in C# / .NET

An example .NET application, written in C#, that uploads assets using the API can be found here (external link, opens in separate tab):

https://bitbucket.org/fotoware/uploaddotnet

This example also shows how to use the .NET framework to construct HTTP multipart requests according to RFC1341:

  • FileData parts are created using the StreamContent class
  • Metadata parts are created using the ByteArrayContent class
  • JSON is rendered using a JavaScriptSerializer.

This is much easier and less error-prone than crafting the requests manually. Also, we recommend rendering JSON using a serializer rather than low-level string operations, as this automatically takes care of escaping and eliminates the threat of JSON injection attacks. Different HTTP client libraries for different programming platforms support similar functionality.

  • Was this article helpful?