Nuxeo/Blogs

Product & Development / All about the Nuxeo Platform, from strategy to feature highlights to dev tricks

[Q&A Friday] How to Upload Files and Bind Them to Documents Using the REST API

with 3 comments

How to upload files to Nuxeo

How 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 file=@myFile.zip -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 file=@myOtherFile.zip -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 file=@myVideo.mkv -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!

January 31st, 2014 at 4:59 pm

Posted in Product & Development

Tagged with , ,

About Laurent Doguin

Laurent works as developer and community liaison at Nuxeo, a software company providing a full Enterprise Content Management Platform, open source, for any kind of content-driven application.
  • nsteinmetz

    Hi,

    Can we use this method for async upload ? I imagine a use case for huge files where we would like to create a document, provide metadata and retrieve back some id (at least). Then, the file would be uploaded sometime later via some batch or asynchronous task.

    Is the batch method the best way or is there a better way ?

    Thanks,
    Nicolas

    • nuxeo

      Hi Nicolas,

      Yes you can do that. Once the file is uploaded you can use the Blob.Attach or the Document.Update operation.

      Cheers,
      Laurent

      • nsteinmetz

        Thanks for the confirmation !