cancel
Showing results for 
Search instead for 
Did you mean: 
gavincornwell
Star Collaborator
Star Collaborator

In the we looked at how to navigate the repository, this time we're going to create some files and folders.

As before all of the endpoints we'll cover in this blog post have been provided in a Postman collection and can be imported by clicking the "Run in Postman" button below.

button.svg

Let's start with creating a folder in our home folder. We use the same URL as we did for navigating the repository but this time we'll POST to it and use the -my- alias.

To create a folder named "My Folder" POST the body below using a Content-Type of application/json to http://localhost:8080/alfresco/api/-default-/public/alfresco/versions/1/nodes/-my-/children

{

  "name":"My Folder",

  "nodeType":"cm:folder"

}

This results in a response representing the newly created folder as shown below:

{

  "entry": {

    "aspectNames": [

      "cm:auditable"

    ],

    "createdAt": "2016-10-17T18:30:28.870+0000",

    "isFolder": true,

    "isFile": false,

    "createdByUser": {

      "id": "test",

      "displayName": "Test Test"

    },

    "modifiedAt": "2016-10-17T18:30:28.870+0000",

    "modifiedByUser": {

      "id": "test",

      "displayName": "Test Test"

    },

    "name": "My Folder",

    "id": "de8f6834-1d5a-4137-ab1f-67e6978f1aa8",

    "nodeType": "cm:folder",

    "parentId": "bd8f1283-3e84-4585-aafc-12da26db760f"

  }

}

You may have noticed that slightly more information about the node (aspectNames and properties) is returned by default but even here we are still using a "performance first" principle. The include parameter can also be used with create, see http://localhost:8080/api-explorer/#!/nodes/addNode for the list of extra information you can request.

Let's now create an empty file within our home folder. Once again we'll POST to http://localhost:8080/alfresco/api/-default-/public/alfresco/versions/1/nodes/-my-/children but this time we'll send the following body:

{

  "name": "my-file.txt",

  "nodeType": "cm:content"

}

This results in a response representing the newly created document as shown below:

{

  "entry": {

    "aspectNames": [

      "cm:auditable"

    ],

    "createdAt": "2016-10-17T18:58:38.717+0000",

    "isFolder": false,

    "isFile": true,

    "createdByUser": {

      "id": "test",

      "displayName": "Test Test"

    },

    "modifiedAt": "2016-10-17T18:58:38.717+0000",

    "modifiedByUser": {

      "id": "test",

      "displayName": "Test Test"

    },

    "name": "my-file.txt",

    "id": "e88e9b0f-7975-4398-beb4-db593b0b7aee",

    "nodeType": "cm:content",

    "content": {

      "mimeType": "text/plain",

      "mimeTypeName": "Plain Text",

      "sizeInBytes": 0,

      "encoding": "UTF-8"

    },

    "parentId": "bd8f1283-3e84-4585-aafc-12da26db760f"

  }

}

As well as accepting JSON the same endpoint also accepts multipart/form-data, allowing us to upload content from a standard HTML form or from the command line using curl.

Presuming there is a file named test.txt in the current directory try the following command:

curl -X POST -H "Authorization: Basic dGVzdDp0ZXN0" -H "Content-Type: multipart/form-data; boundary=----FormBoundary7MA4YWxkTrZu0gW" -F "filedata=@test.txt" "http://localhost:8080/alfresco/api/-default-/public/alfresco/versions/1/nodes/-my-/children"

Alternatively, the 3rd request in the Postman collection can be used after selecting a file in the "Body" tab as shown in the screenshot below.

Screen_Shot_2016-10-17_at_20_56_04.png

If you hadn't already noticed, one of the benefits of the API Explorer is that it allows you to "Try it out!" on all documented APIs. Unfortunately the OpenAPI specification does not currently allow multiple content types to be documented for the same endpoint. For POST /nodes/-my-/children we made the decision to focus the API Explorer on JSON to allow the creation of folders and files. We have however fully documented what is possible via multipart/form-data, we'll discuss a few of those options next.

To specify the name of the file that gets created you can use a form field called name as shown in the screenshot below. You can try this for yourself via the 4th request in the Postman collection.

Screen Shot 2016-10-18 at 20.04.27.png

When uploading content it's quite common for a file with the same name to exist, this will generate an error by default, to avoid the error the autoRename form field can be used as shown below. You can try this for yourself via the 5th request in the Postman collection. If a file name clash is detected a suffix will be added to the file name, for example my-file.txt will become my-file-1.txt.

Screen Shot 2016-10-18 at 20.25.36.png

The same thing can be achieved whilst creating folders and empty files via the same named query parameter, for example: http://localhost:8080/alfresco/api/-default-/public/alfresco/versions/1/nodes/-my-/children?autoRena...

In some scenarios the path of the destination folder is known, so to avoid having to lookup the id of the folder a relativePath form field can be provided as shown in the screenshot below. You can try this for yourself via the 6th request in the Postman collection.

Screen Shot 2016-10-18 at 21.21.29.png

This will create a file named "my-file.txt" in the folder we created earlier i.e. in "/Company Home/User Homes/test/My Folder". The same thing can be achieved whilst creating folders and empty files by using the same named property in the body as follows:

{

   ...

   "relativePath": "/My Folder"

}

Another feature of the repository we can control when uploading content is the generation of a rendition. To have the thumbnail rendition used by Share generated, provide a renditions form field with a value of doclib as shown in the screenshot below. You can try this for yourself via the 7th request in the Postman collection.

Screen Shot 2016-10-18 at 21.43.36.png

Currently only one rendition can be requested, we plan to allow multiple in the future hence the plural form field name.

Finally, let's take a look at how we set properties. Any other form field will be presumed to represent a property to set. The screenshot below and the last request in the Postman collection shows how to set the cm:title, cm:description and exif:manufacturer properties. Properties have to follow the prefix:localname format and be a registered property via the content model otherwise they are silently ignored.

Screen Shot 2016-10-18 at 21.43.58.png

If we take a look at the response we'll see that the appropriate aspects have also been automatically applied.

{

  "entry": {

    ...

    "aspectNames": [

      "cm:versionable","cm:titled","cm:auditable","cm:author","exif:exif"

    ],

    "properties": {

      "cm:title": "The Title",

      "cm:versionType": "MAJOR",

      "cm:versionLabel": "1.0",

      "exif:manufacturer": "Canon",

      "cm:description":"The Description"

    }

  }

}

We've covered a lot of ground in this post but we still haven't looked at all the capabilities available; overwriting, versioning, custom types and associations will all be covered in future posts. we'll be looking at how to retrieve, update and delete files & folders.

34 Comments
zhihailiu
Champ on-the-rise
Champ on-the-rise

I must have lost my mind... Thank you!

zhihailiu
Champ on-the-rise
Champ on-the-rise

Hi Gavin,

A related question - can I create a node and set its permissions in one POST call? or do I have to do POST to create the node and then PUT to update permissions? I tried below (even with include=permissions). The node was created but withe default/inherited permissions. Thanks.

POST /nodes/{nodeId}/children

{  
    "name":"Test",
    "nodeType":"cm:folder",
    "properties":{  
        "cm:title":"Test"
    },
    "permissions":{  
        "isInheritanceEnabled":false,
        "locallySet":[  
            {  
                "authorityId":"joe",
                "name":"SiteManager",
                "accessStatus":"ALLOWED"
            }
        ]
    }
}

gavincornwell
Star Collaborator
Star Collaborator

That's a great question! Unfortunately we don't support that currently so yes, you'd have to do a POST followed by a PUT.

This is something we should support so please raise an enhancement request at issues.alfresco.com.

lcelenza
Champ in-the-making
Champ in-the-making

Hi Gavin,

I'm trying to create a node with data content in .NET (C#) calling the nodes/{nodeId}/children endpoint, but I can't seem to make it work. It's driving me nuts! So far I only managed to make it work using Postman. I tried with both RestSharp and HttpClient from WebApi.Client nuget package, but the result is always 400 Bad Request. Here's the response content:

{"error":{"errorKey":"Could not read content from HTTP request body: Unexpected character ('-' (code 45)) in numeric value: expected digit (0-9) to follow minus sign, for valid numeric value\n at [Source: java.io.BufferedReader@4e290940; line: 1, column: 3]","statusCode":400,"briefSummary":"00180071 Could not read content from HTTP request body: Unexpected character ('-' (code 45)) in numeric value: expected digit (0-9) to follow minus sign, for valid numeric value\n at [Source: java.io.BufferedReader@4e290940; line: 1, column: 3]","stackTrace":"Per motivi di sicurezza l'analisi dello stack non viene più visualizzata, ma viene mantenuta la proprietà per le versioni precedenti.","descriptionURL":"https://api-explorer.alfresco.com"}}

Any help would be much appreciated, thanks

gavincornwell
Star Collaborator
Star Collaborator

This sounds like a client issue to me, from the error message it looks like the client library is sending a malformed request body with the request, it should be a JSON body. Are you correctly setting the Content-Type for the request to be "application/json"?

The easiest way to debug this would be to place a HTTP proxy in between your client and server and record the traffic being sent by the .NET client. 

ivanovpavel1983
Champ on-the-rise
Champ on-the-rise

Hi Gavin!

Is it possible to create node of sys:base class?

I got an error:

The request is:

I have requested post /nodes/{nodeId}/children

otp:referenceRequiredDocuments is :

{nodeId} is folder (cm:folder class):

gavincornwell
Star Collaborator
Star Collaborator

No, as the error message says it's only possible to create sub-types of cm:cmobject via the REST API at this time.

The "sys" namespace is reserved for system level objects that should generally remain hidden from APIs/UIs.  Is there a reason you need to extend from sys:base? I would recommend extending from cm:cmobject.

ivanovpavel1983
Champ on-the-rise
Champ on-the-rise

We have types (contacts, applications, operations) without content. We have otp:document that extends cm:cmobject and associations for join contacts, applications, operations to documents... Is it correct to extend cmSmiley Surprisedbject for types without content?

gavincornwell
Star Collaborator
Star Collaborator

If you have custom types without content the recommended type to extend is "cm:cmobject" whereas if you have custom types with content the recommended type to extend is "cm:content".

ivanovpavel1983
Champ on-the-rise
Champ on-the-rise

Hello, Gavin.

We used inherit from sys:base according to book alfresco developers guide 5.0 ((

Can we change parent class of our objects from sys:base to cm:cmobject after production system start?