In the last post we looked at how to create files and folders in the repository, this time we're going to retrieve and update node information, retrieve and update content and remove nodes from the repository.
To keep with tradition, all of the endpoints we'll cover in this post have been provided in a Postman collection and can be imported by clicking on the "Run in Postman" button below.
There is something a little different about this one though, it uses the testing capabilities of Postman. After the create request is executed some JavaScript is run to grab the id of the newly created file and store it in a global variable. The URL of subsequent requests in the collection then refer to the global variable using Postman's {{variable}} syntax. Explaining the full testing capabilities of Postman is beyond the scope of this blog post so I'll leave that as an exercise for the reader!
OK, let's start by creating an empty file. 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": "content.txt",
"nodeType": "cm:content",
"properties": {
"cm:title": "The Title"
}
}
Copy the value of the id property from the resulting response (or use the first request in the Postman collection).
Now let's retrieve some information about this node. We do this by doing a GET on http://localhost:8080/alfresco/api/-default-/public/alfresco/versions/1/nodes/8c37b5b7-b96f-49ef-817... (you'll obviously need to replace the id with the one you copied from your response or use the 2nd request in the Postman collection). This results in the following response:
{
"entry": {
"isFile": true,
"createdByUser": {
"id": "test",
"displayName": "Test Test"
},
"modifiedAt": "2016-11-01T14:57:24.388+0000",
"nodeType": "cm:content",
"content": {
"mimeType": "text\/plain",
"mimeTypeName": "Plain Text",
"sizeInBytes": 0,
"encoding": "UTF-8"
},
"parentId": "bd8f1283-3e84-4585-aafc-12da26db760f",
"aspectNames": [
"cm:titled",
"cm:auditable"
],
"createdAt": "2016-11-01T14:57:24.388+0000",
"isFolder": false,
"modifiedByUser": {
"id": "test",
"displayName": "Test Test"
},
"name": "my-file.txt",
"id": "8c37b5b7-b96f-49ef-817e-9808bf2309f9",
"properties": {
"cm:title": "The Title"
}
}
}
All the data returned by the /nodes/{id}/children endpoint we examined in the second post is present plus the node's properties (line 29) and a list of aspect names (line 17). As we saw with create in the previous post this endpoint is also following our "performance first" principle. If we wanted to also determine whether the node represents a link and see it's full path, we can use the include query parameter to ask for this data, for example (3rd request in the Postman collection😞
{
"entry": {
"isLink": false,
"isFolder": false,
"isFile": true,
"path": {
"name": "/Company Home/User Homes/test",
"isComplete": true,
"elements": [
{
"id": "03acc816-b42f-4d87-ab1f-4d4ae16e73ef",
"name": "Company Home"
},
{
"id": "fb402fa3-3a59-446e-a69e-a1c769b62281",
"name": "User Homes"
},
{
"id": "bd8f1283-3e84-4585-aafc-12da26db760f",
"name": "test"
}
]
},
...
}
}
Take a look at the OpenAPI specification http://localhost:8080/api-explorer/#!/nodes/getNode for other additional data you can request.
Let's now turn our attention to updating a node. We have decided to implement partial update via PUT (although technically this is not RESTful we feel it's worth bending the rules here to keep things as simple as possible for clients) meaning the client only needs to send the data that is changing, with one exception, that we'll come to shortly.
To set some properties we use the same base URL (4th request in the Postman collection) of http://localhost:8080/alfresco/api/-default-/public/alfresco/versions/1/nodes/8c37b5b7-b96f-49ef-817... but PUT a body using a Content-Type of application/json.
{
"properties":
{
"cm:description": "The Description",
"exif:manufacturer": "Canon"
}
}
The response shows the state of the updated node, note that the exif aspect has also been added automatically (line 20).
{
"entry": {
"isFile": true,
"createdByUser": {
"id": "test",
"displayName": "Test Test"
},
"modifiedAt": "2016-11-02T00:40:51.931+0000",
"nodeType": "cm:content",
"content": {
"mimeType": "text\/plain",
"mimeTypeName": "Plain Text",
"sizeInBytes": 0,
"encoding": "UTF-8"
},
"parentId": "bd8f1283-3e84-4585-aafc-12da26db760f",
"aspectNames": [
"cm:titled",
"cm:auditable",
"exif:exif"
],
"createdAt": "2016-11-01T14:57:24.388+0000",
"isFolder": false,
"modifiedByUser": {
"id": "test",
"displayName": "Test Test"
},
"name": "my-file.txt",
"id": "8c37b5b7-b96f-49ef-817e-9808bf2309f9",
"properties": {
"cm:title": "The Title",
"exif:manufacturer": "Canon",
"cm:description": "The Description"
}
}
}
PUT can also be used to rename by just providing a cm:name property in the properties as shown below:
{
"properties":
{
"cm:name": "renamed-name.txt"
}
}
Alternatively, the top level name property can also be used (5th request in the Postman collection😞
{
"name": "renamed-file.txt"
}
Similarly, the owner of the node can be updated, just provide the cmwner property as follows (6th request in the Postman collection😞
{
"properties":
{
"cm:owner": "gavinc"
}
}
As mentioned earlier there is one exception to the partial update rule and that is for managing aspects. To change the aspects applied to a node the whole complete array has to be provided. Any aspects the node has applied but are not present in the array will be removed. Conversely, any aspects in the array that the node does not have applied are added.
To remove the exif aspect from the node we created earlier PUT the following body (7th request in the Postman collection😞
{
"aspectNames": [
"cm:titled",
"cm:ownable",
"cm:auditable"
]
}
Finally, the type of the node can also be changed by updating the nodeType property, for example to change our node type to cm:savedquery use the following body (8th request in the Postman collection😞
{
"nodeType": "cm:savedquery"
}
In the examples above we've used a file, everything we went through can obviously also be done for folders.
Let's now turn our attention to the actual content. At the start of the post we created an empty text file, you can see this via the content property:
"content": {
"mimeType": "text/plain",
"mimeTypeName": "Plain Text",
"sizeInBytes": 0,
"encoding": "UTF-8"
}
To set some plain text content do a PUT against http://localhost:8080/alfresco/api/-default-/public/alfresco/versions/1/nodes/8c37b5b7-b96f-49ef-817... using a Content-Type of text/plain and the following body (9th request in the Postman collection😞
This is the initial content for the file.
The response will show the content has been updated and the encoding set accordingly:
{
"entry": {
....
"content": {
"mimeType": "text/plain",
"mimeTypeName": "Plain Text",
"sizeInBytes": 41,
"encoding": "ISO-8859-1"
}
}
}
The PUT endpoint accepts any binary stream so we could also use Postman to choose a file to upload as shown in the screenshot below:
To retrieve the content simply use a GET against the content URL (10th request in the Postman collection😞
The last thing we're going to cover in this post is deleting. To delete the file we just created use the DELETE method against the URL we've been using throughout this post (11th request in the Postman collection), for example:
This will actually perform a soft delete, the node gets moved to the trash can so it can be restored if necessary, we'll cover the trash can endpoints in a future post. If you want to take a look before then have a look through the documentation.
To permanently delete the node i.e. skip the trash can, use the permanent query parameter set to true, for example (12th request in the Postman collection😞
Hopefully you've found these posts useful so far, if there's anything I can improve to make things easier or any other suggestions, please let me know via comments.
In the next post we're going to start looking into some more advanced topics, starting with versioning and locking.