How to upload files to NuxeoHow to upload files to Nuxeo

Today I have chosen a question from Bauke Roo who asks how to upload a file(s) to Nuxeo and bind it to a document using the REST API.

This is probably one of the first things someone would like to test when playing with the REST API. I thought I would post the answer on the blog so that everyone knows how to do it.

There are currently two ways to upload files. The first one is to send a blob using the standard HTTP MultiPart encoding. This is not always the best idea. You could for instance use a client that does not support MultiPart encoding or you have several files to send, but prefer to send them as separated chunks (because a web server in front of Nuxeo limits POST size).

Maybe you want to upload a file(s) as soon as possible and then run the operation when everything has been uploaded on the server, like on a mobile phone, for example. If you create a document from an image you’ve taken with your phone camera, you’ll see a progress bar. As the file starts to upload, you can fill in the rest of the metadata. Then, as soon as the upload is finished, the operation creating the document can be called. So, yes, we don’t recommend uploading blobs using HTTP MultiPart encoding.

Instead, we recommend using the batch/upload endpoint. It represents a place on the system where you can upload temporary files and do something with them later. To create a batch you have to do an HTTP POST like this:

POST http://localhost:8080/nuxeo/api/v1/automation/batch/upload
X-Batch-Id: mybatchid
X-File-Idx:0
X-File-Name:myFile.zip
-----------------------
The content of the file

Using the command line tool curl, it translates to this:

curl -H "X-Batch-Id: mybatchid" -H "X-File-Idx:0" -H "X-File-Name:myFile.zip" -F [email protected] -u Administrator:Administrator http://localhost:8080/nuxeo/api/v1/automation/batch/upload

Which will return something like:

{"uploaded":"true","batchId":"mybatchid"}

The batch has been created. Let’s see what is inside that batch:

curl -u Administrator:Administrator http://localhost:8080/nuxeo/api/v1/automation/batch/files/mybatchid
[{"name":"myFile.zip","size":5809}]

The server’s response contains the list of files and associated sizes. If you upload another file with another index, you’ll have the following:

curl -H "X-Batch-Id: mybatchid" -H "X-File-Idx:1" -H "X-File-Name:myOtherFile.zip" -F [email protected] -u Administrator:Administrator http://localhost:8080/nuxeo/api/v1/automation/batch/upload
curl -u Administrator:Administrator http://localhost:8080/nuxeo/api/v1/automation/batch/files/mybatchid
[{"name":"myFile.zip","size":5809},{"name":"myOtherFile.zip","size":5819}]

As you can see a batch is a simple list of files uploaded to the server, accessible through a unique id. Now that we have some files on the server, we want to use them. Let’s create a new document using this batch.

POST http://localhost:8080/nuxeo/api/v1/path/default-domain/workspaces/myworkspace
{
  "entity-type": "document",
  "name":"myNewDoc",
  "type": "File",
  "properties" : {
    "dc:title":"My new doc",
    "file:content": {
      "upload-batch":"mybatchid",
      "upload-fileId":"0"
    }
  }
}
curl -X POST -H "Content-Type: application/json" -u Administrator:Administrator -d '{ "entity-type": "document", "name":"myNewDoc", "type": "File", "properties" : { "dc:title":"My new doc","file:content": {"upload-batch":"mybatchid","upload-fileId":"0"}}}' http://localhost:8080/nuxeo/api/v1/path/default-domain/workspaces/myworkspace

This will create a new File document with the first element of our batch (because of "upload-fileId":"0") in the main file field file:content. Once our batch is used, it’s automatically removed. So now we have lost our second file. To add both of them to the files schema, you have to do it like this:

curl -X POST -H "Content-Type: application/json" -u Administrator:Administrator -d '
  { "entity-type" : "document",
  "name" : "myNewDoc2",
  "type" : "File",
  "properties" : { "dc:title" : "My new doc2",
      "files:files" : [ { "file" : { "upload-batch" : "mybatchid",
                "upload-fileId" : "0"
              },
            "filename" : "myFile.zip"
          },
          { "file" : { "upload-batch" : "mybatchid",
                "upload-fileId" : "1"
              },
            "filename" : "myOtherFile.zip"
          }
        ]
    }
}' http://localhost:8080/nuxeo/api/v1/path/default-domain/workspaces/workspace

This way you have to define at least the title, path and type of the document. If you don’t want to define anything, and use the file information just like when using drag’n drop, you can use the batch/execute endpoint. This time the document is specified in the context map of the request instead of the endpoint.

curl -X POST -H "Content-Type: application/json+nxrequest" -d '{"params":{"operationId":"FileManager.Import","batchId":"mybatchid"},"context":{"currentDocument":"/default-domain/workspaces/workspace"} }' -u Administrator:Administrator http://localhost:8080/nuxeo/site/automation/batch/execute

Sometimes the document created is not exactly using the type you expected. This creation method uses the mime type of the file to set the document type. If you want more control over this, you can specify the mime type of the file when uploading it using the X-File-Type HTTP header.

curl -H "X-Batch-Id: mybatchid" -H "X-File-Idx:0" -H "X-File-Name:myVideo.mkv" -H "X-File-Type:video/x-matroska" -F [email protected] -u Administrator:Administrator http://localhost:8080/nuxeo/api/v1/automation/batch/upload

You now should be all set to use files with the REST API!