Using Object APIs With Base64 Encoded Files
Liferay DXP 2024.Q2+/Portal 7.4 GA120+
When creating object entries with attachment fields through APIs, you can generally upload files from your computer or use files uploaded to the Documents and Media application. Both scenarios require multiple steps.
You can either upload the document and provide its ID or external reference code (ERC) when posting the object entry via API, or you can post the object entry via API and attach the file to it later through the UI.
Alternatively, you can post object entries with attachments in one step by making a POST request and including a Base64-encoded file in the request body.
Before proceeding, set up a new Liferay DXP/Portal 7.4 instance and prepare the provided tutorial code.
Setting Up a Liferay Instance
Start a new Liferay instance by running
docker run -it -m 8g -p 8080:8080 liferay/portal:7.4.3.120-ga120
Sign in to Liferay at http://localhost:8080. Use the email address test@liferay.com and the password test. When prompted, change the password to learn.
Follow these steps to create a basic object for this tutorial:
-
Open the Global Menu (), go to the Control Panel tab, and click Objects.
-
Click the Add button () and enter these values:
Field Value Label Able Plural Label Ables Name Able -
Select the new Object draft, go to the Fields tab, and add the following fields:
Label Field Name Type Request Files usersComputerAttachment1 usersComputerAttachment1 Attachment Upload Directly from the User's Computer
usersComputerAttachment2 usersComputerAttachment2 Attachment Upload Directly from the User's Computer
(Toggle theShow Files in Documents and Media
option)docsAndMediaAttachment docsAndMediaAttachment Attachment Upload or Select from Documents and Media Item Selector
Alternatively, execute
ObjectDefinition_POST_ToInstance.sh
to create the object definition. Afterward, you can access the object definition at Global Menu → Control Panel → Objects and continue with the next step../ObjectDefinition_POST_ToInstance.sh
-
In the Details tab, select Company as the Scope, Object under Panel Link, and click Publish.
ImportantFor this tutorial, you must use the above values.
Once published, you can access the object via APIs.
Preparing the Sample Code
Run the following commands to download and unzip the provided sample code:
curl https://resources.learn.liferay.com/dxp/latest/en/building-applications/objects/understanding-object-integrations/using-custom-object-apis/liferay-p7x7.zip -O
unzip liferay-p7x7.zip
These scripts include the following APIs:
HTTP Method | HTTP Endpoint | Description |
---|---|---|
GET | / | Returns a complete list of object entries in a Liferay instance; results can be paginated, filtered, searched, and sorted. |
POST | / | Creates object entries using the details provided in the API call. |
PUT | /[objectNameId] | Replaces the specified Object entry’s details with those provided in the API call |
DELETE | /[objectNameId] | Deletes the specified Object entry and returns a 204 if the operation succeeds |
-
After downloading the sample code, navigate to the
curl
folder in theliferay-p7x7
project.cd liferay-p7x7/curl
Posting an Attachment Uploaded Directly From the User’s Computer
To create an object entry with an attachment using the Upload Directly from the User's Computer
Request Files option,
-
Execute
Able_POST_FromUsersComputer1.sh
. This creates an object entry with a Base64 file attached to it../Able_POST_FromUsersComputer1.sh
Use the
fileBase64
parameter to attach the file to the object entry.... --data-raw '{ "externalReferenceCode": "ATTACHMENT_FROM_USERS_COMPUTER_1", "usersComputerAttachment1": { "fileBase64": "iVB0...gg==", "name": "AttachmentFromUsersComputer1.png" } ...
The terminal shows a similar output.
{ "actions": { "permissions": { "method": "GET", "href": "http://localhost:8080/o/c/ables/32268/permissions" }, "get": { "method": "GET", "href": "http://localhost:8080/o/c/ables/32268" }, "replace": { "method": "PUT", "href": "http://localhost:8080/o/c/ables/32268" }, "update": { "method": "PATCH", "href": "http://localhost:8080/o/c/ables/32268" }, "delete": { "method": "DELETE", "href": "http://localhost:8080/o/c/ables/32268" } }, "creator": { "additionalName": "", "contentType": "UserAccount", "familyName": "Test", "givenName": "Test", "id": 20122, "name": "Test Test" }, "dateCreated": "2024-06-05T16:37:26Z", "dateModified": "2024-06-05T16:37:26Z", "externalReferenceCode": "ATTACHMENT_FROM_USERS_COMPUTER_1", "id": 32268, "keywords": [], "status": { "code": 0, "label": "approved", "label_i18n": "Approved" }, "taxonomyCategoryBriefs": [], "usersComputerAttachment1": { "id": 32263, "link": { "href": "/documents/32260/32262/AttachmentFromUsersComputer1.png/f0a02e6a-8eeb-d021-bfdd-82da1afab1cf?version=1.0&t=1717605446526&download=true&objectDefinitionExternalReferenceCode=ABLE&objectEntryExternalReferenceCode=ATTACHMENT_FROM_USERS_COMPUTER_1", "label": "AttachmentFromUsersComputer1.png" }, "name": "AttachmentFromUsersComputer1.png" } }
Note that the response doesn’t contain the
fileBase64
encoding by default. See Getting the Attachment’s Content in the Response to learn more.
Execute Able_POST_FromUsersComputer2.sh
to create an object entry with an attachment using the Upload Directly from the User's Computer
Request Files option and the Show Files in Documents and Media
option toggled on. Note that specifying a folder is unnecessary. The folder selection is based automatically on the company for company-scoped object definitions or the site for site-scoped object definitions.
./Able_POST_FromUsersComputer2.sh
Posting an Attachment Uploaded or Selected From The Documents and Media Item Selector
-
Execute
DocumentFolder_POST_ToSite.sh
to create the folder to store the uploaded file. Use the site ID as a parameter. In this example, the site ID is20117
TipLocate the site ID at Site Menu () → Configuration → Site Settings → Site Configuration under Platform.
./DocumentFolder_POST_ToSite.sh [site-id]
The terminal should display a similar output.
{ "actions" : { "subscribe" : { "method" : "PUT", "href" : "http://localhost:8080/o/headless-delivery/v1.0/document-folders/32258/subscribe" }, "unsubscribe" : { "method" : "PUT", "href" : "http://localhost:8080/o/headless-delivery/v1.0/document-folders/32258/unsubscribe" }, "get" : { "method" : "GET", "href" : "http://localhost:8080/o/headless-delivery/v1.0/document-folders/32258" }, "replace" : { "method" : "PUT", "href" : "http://localhost:8080/o/headless-delivery/v1.0/document-folders/32258" }, "update" : { "method" : "PATCH", "href" : "http://localhost:8080/o/headless-delivery/v1.0/document-folders/32258" }, "delete" : { "method" : "DELETE", "href" : "http://localhost:8080/o/headless-delivery/v1.0/document-folders/32258" } }, "creator" : { "additionalName" : "", "contentType" : "UserAccount", "familyName" : "Test", "givenName" : "Test", "id" : 20122, "name" : "Test Test" }, "customFields" : [ ], "dateCreated" : "2024-06-05T16:37:12Z", "dateModified" : "2024-06-05T16:37:12Z", "description" : "This folder stores the attachment files for this exercise.", "externalReferenceCode" : "ABLE_FOLDER", "id" : 32258, "name" : "Able Folder", "numberOfDocumentFolders" : 0, "numberOfDocuments" : 0, "siteId" : 20117, "subscribed" : false }
-
Execute
Able_POST_FromDocumentsAndMedia.sh
. This creates an object entry with a Base64 file attached to it and places it in the recently created folder. Use the folder’s ERC and the site ID as parameters. In this example, the ERC isABLE_FOLDER
and the site ID is20117
../Able_POST_FromDocumentsAndMedia.sh [ERC] [site-id]
Use the
folder
parameter to add theexternalReferenceCode
and thesiteId
to store the document.... "folder": { "externalReferenceCode": "'${1}'", "siteId": "'${2}'" }, ...
NoteIf the
siteId
or theERC
are not included, null, or empty, the POST request still works, and the file is uploaded to the default site’s root folder.The terminal should display a similar output.
{ "actions" : { "permissions" : { "method" : "GET", "href" : "http://localhost:8080/o/c/ables/32337/permissions" }, "get" : { "method" : "GET", "href" : "http://localhost:8080/o/c/ables/32337" }, "replace" : { "method" : "PUT", "href" : "http://localhost:8080/o/c/ables/32337" }, "update" : { "method" : "PATCH", "href" : "http://localhost:8080/o/c/ables/32337" }, "delete" : { "method" : "DELETE", "href" : "http://localhost:8080/o/c/ables/32337" } }, "creator" : { "additionalName" : "", "contentType" : "UserAccount", "familyName" : "Test", "givenName" : "Test", "id" : 20122, "name" : "Test Test" }, "dateCreated" : "2024-06-05T16:37:36Z", "dateModified" : "2024-06-05T16:37:36Z", "externalReferenceCode" : "ATTACHMENT_FROM_DOCS_AND_MEDIA", "id" : 32337, "keywords" : [ ], "status" : { "code" : 0, "label" : "approved", "label_i18n" : "Approved" }, "taxonomyCategoryBriefs" : [ ], "docsAndMediaAttachment" : { "id" : 32332, "link" : { "href" : "/documents/20119/0/AttachmentFromDocumentsAndMedia.png/bbe75f48-04ce-2967-1721-973655b9a853?version=1.0&t=1717605455991&download=true&objectDefinitionExternalReferenceCode=ABLE&objectEntryExternalReferenceCode=ATTACHMENT_FROM_DOCS_AND_MEDIA", "label" : "AttachmentFromDocumentsAndMedia.png" }, "name" : "AttachmentFromDocumentsAndMedia.png" } }
NoteUploading a file with the same name as an existing file in the destination folder results in the new file being renamed with a unique sequential number in parentheses (i.e.,
Name (n).extension
).Note that the response doesn’t contain the
fileBase64
encoding by default. See Getting the Attachment’s Content in the Response to learn more.
Getting a List of All Entries
-
Run
Able_GET_FromCompany.sh
to get a list of all entries../Able_GET_FromCompany.sh
The response should include information about the attached file such as the
id
, alink
where you can download it, itslabel
, and itsname
.... "dateCreated" : "2024-06-05T16:37:26Z", "dateModified" : "2024-06-05T16:37:26Z", "externalReferenceCode" : "ATTACHMENT_FROM_USERS_COMPUTER_1", "id" : 32268, "keywords" : [ ], "status" : { "code" : 0, "label" : "approved", "label_i18n" : "Approved" }, "taxonomyCategoryBriefs" : [ ], "usersComputerAttachment1" : { "id" : 32263, "link" : { "href" : "/documents/32260/32262/AttachmentFromUsersComputer1.png/f0a02e6a-8eeb-d021-bfdd-82da1afab1cf?version=1.0&t=1717605446526&download=true&objectDefinitionExternalReferenceCode=ABLE&objectEntryExternalReferenceCode=ATTACHMENT_FROM_USERS_COMPUTER_1", "label" : "AttachmentFromUsersComputer1.png" }, "name" : "AttachmentFromUsersComputer1.png" } ...
Note that the response contains the address for the files, but it doesn’t contain the
fileBase64
encodings by default. See Getting the Attachment’s Content in the Response to learn more.
Updating an Object Entry With an Attachment
Use a PUT request to replace the entire object entry with the details provided in the API call. In this case, the same structure used to POST the object entry must be used with the PUT request, with alterations to the specific fields you wish to update.
Similarly, although a PATCH request would include only specific fields to be changed in the structure, you must ensure the PATCH structure and content match those used during creation too.
To alter an entry using a PUT request,
-
Execute
Able_PUT_ById.sh
to change the external reference code and the name of the file attached to the object entry. Use the object entry ID as a parameter.In this example, the ID for the
ATTACHMENT_FROM_USERS_COMPUTER_1
entry retrieved in the GET request is32268
../Able_PUT_ById.sh [Object-ID]
A response displays the updated information for the object entry. Note that the response contains the address for the file, but it doesn’t contain the
fileBase64
encoding by default. See Getting the Attachment’s Content in the Response to learn more. -
The external reference code is now
ATTACHMENT_FROM_USERS_COMPUTER_1_ALTERED
and the image is namedAttachmentFromUsersComputer1Altered.png
."dateCreated" : "2024-06-05T16:37:26Z", "dateModified" : "2024-06-05T16:38:11Z", "externalReferenceCode" : "ATTACHMENT_FROM_USERS_COMPUTER_1_ALTERED", ... "link" : { "href" : "/documents/32260/32262/AttachmentFromUsersComputer1Altered.png/da5fe5a1-c36c-e016-846e-20720b7469a8?version=1.0&t=1717605491796&download=true&objectDefinitionExternalReferenceCode=ABLE&objectEntryExternalReferenceCode=ATTACHMENT_FROM_USERS_COMPUTER_1_ALTERED", "label" : "AttachmentFromUsersComputer1Altered.png" }, "name" : "AttachmentFromUsersComputer1Altered.png" }
Deleting an Object Entry With an Attachment
-
Execute
Able_DELETE_ById.sh
to delete the object entry and its attachment. Use the object entry ID as a parameter../Able_DELETE_ById.sh [Object-ID]
-
There is no content in the response.
Getting the Attachment’s Content in the Response
To get the Base64 encoded file in the response, you must request it as a nested field by using the nestedFields=[fieldName].fileBase64
query parameter. This avoids calculating the Base64 encoding if the user hasn’t requested it.
Execute this cURL command in your terminal to get the attachment’s content for the entry with the ATTACHMENT_FROM_USERS_COMPUTER_2
ERC:
curl \
"http://localhost:8080/o/c/ables/by-external-reference-code/ATTACHMENT_FROM_USERS_COMPUTER_2?nestedFields=usersComputerAttachment2.fileBase64" \
--request "GET" \
--user "test@liferay.com:learn"
The terminal should display a similar output with the Base64 encoded file, its ID, link, label, and name.
...
"usersComputerAttachment2" : {
"fileBase64" : "iVBORw0KG...kJggg==",
"id" : 32283,
"link" : {
"href" : "/documents/20119/32281/AttachmentFromUsersComputer2.png/266a539c-506c-8273-96d2-15206933b993?version=1.0&t=1717605449655&download=true&objectDefinitionExternalReferenceCode=ABLE&objectEntryExternalReferenceCode=ATTACHMENT_FROM_USERS_COMPUTER_2",
"label" : "AttachmentFromUsersComputer2.png"
},
"name" : "AttachmentFromUsersComputer2.png"
}
Getting the Attachment’s Folder in the Response
To get the folder where the Base64 encoded file is stored in the response, you must request it as a nested field by using the nestedFields=[fieldName].folder
query parameter. This avoids unnecessary access to data.
Execute this cURL command in your terminal to get the folder for the entry with the ATTACHMENT_FROM_DOCS_AND_MEDIA
ERC:
curl \
"http://localhost:8080/o/c/ables/by-external-reference-code/ATTACHMENT_FROM_DOCS_AND_MEDIA?nestedFields=docsAndMediaAttachment.folder" \
--request "GET" \
--user "test@liferay.com:learn"
The terminal shows a similar output with the folder’s ERC
and siteId
where it’s located.
...
"docsAndMediaAttachment" : {
"folder" : {
"externalReferenceCode" : "ABLE_FOLDER",
"siteId" : 20117
},
...