diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
index 1cab6d61e..3b08eff07 100644
--- a/.github/workflows/pull-request.yml
+++ b/.github/workflows/pull-request.yml
@@ -171,6 +171,8 @@ jobs:
             id: 12
           - name: "search"
             id: 13
+          - name: "upload-download-actions"
+            id: 14
     steps:
       - name: Checkout
         uses: actions/checkout@v3
diff --git a/e2e/playwright/upload-download-actions/.eslintrc.json b/e2e/playwright/upload-download-actions/.eslintrc.json
new file mode 100644
index 000000000..597571811
--- /dev/null
+++ b/e2e/playwright/upload-download-actions/.eslintrc.json
@@ -0,0 +1,26 @@
+{
+  "extends": "../../../.eslintrc.json",
+  "ignorePatterns": [
+    "!**/*"
+  ],
+  "overrides": [
+    {
+      "files": [
+        "*.ts"
+      ],
+      "parserOptions": {
+        "project": [
+          "e2e/playwright/upload-download-actions/tsconfig.e2e.json"
+        ],
+        "createDefaultProgram": true
+      },
+      "plugins": [
+        "rxjs",
+        "unicorn"
+      ],
+      "rules": {
+        "@typescript-eslint/no-floating-promises": "off"
+      }
+    }
+  ]
+}
diff --git a/e2e/playwright/upload-download-actions/exclude.tests.json b/e2e/playwright/upload-download-actions/exclude.tests.json
new file mode 100644
index 000000000..9e26dfeeb
--- /dev/null
+++ b/e2e/playwright/upload-download-actions/exclude.tests.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/e2e/playwright/upload-download-actions/playwright.config.ts b/e2e/playwright/upload-download-actions/playwright.config.ts
new file mode 100644
index 000000000..243dace7b
--- /dev/null
+++ b/e2e/playwright/upload-download-actions/playwright.config.ts
@@ -0,0 +1,44 @@
+/*!
+ * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
+ *
+ * Alfresco Example Content Application
+ *
+ * This file is part of the Alfresco Example Content Application.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * The Alfresco Example Content Application is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Alfresco Example Content Application is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import { PlaywrightTestConfig } from '@playwright/test';
+import { CustomConfig, getGlobalConfig, getExcludedTestsRegExpArray } from '@alfresco/playwright-shared';
+import EXCLUDED_JSON from './exclude.tests.json';
+
+const config: PlaywrightTestConfig<CustomConfig> = {
+  ...getGlobalConfig,
+
+  grepInvert: getExcludedTestsRegExpArray(EXCLUDED_JSON, 'Upload Download Actions'),
+  projects: [
+    {
+      name: 'Upload Download Actions',
+      testDir: './src/tests',
+      use: {
+        users: []
+      }
+    }
+  ]
+};
+
+export default config;
diff --git a/e2e/playwright/upload-download-actions/project.json b/e2e/playwright/upload-download-actions/project.json
new file mode 100644
index 000000000..5f74836e3
--- /dev/null
+++ b/e2e/playwright/upload-download-actions/project.json
@@ -0,0 +1,22 @@
+{
+  "name": "upload-download-actions-e2e",
+  "$schema": "../../../node_modules/nx/schemas/project-schema.json",
+  "sourceRoot": "e2e/playwright/upload-download-actions",
+  "projectType": "application",
+  "targets": {
+    "e2e": {
+      "executor": "nx:run-commands",
+      "options": {
+        "commands": ["npx playwright test --config=e2e/playwright/upload-download-actions/playwright.config.ts"]
+      },
+      "configurations": {
+        "production": {
+          "devServerTarget": "content-ce:serve:production"
+        }
+      }
+    },
+    "lint": {
+      "executor": "@angular-eslint/builder:lint"
+    }
+  }
+}
diff --git a/e2e/playwright/upload-download-actions/src/tests/download.e2e.ts b/e2e/playwright/upload-download-actions/src/tests/download.e2e.ts
new file mode 100644
index 000000000..9f28d2255
--- /dev/null
+++ b/e2e/playwright/upload-download-actions/src/tests/download.e2e.ts
@@ -0,0 +1,85 @@
+/*!
+ * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
+ *
+ * Alfresco Example Content Application
+ *
+ * This file is part of the Alfresco Example Content Application.
+ * If the software was purchased under a paid Alfresco license, the terms of
+ * the paid license agreement will prevail. Otherwise, the software is
+ * provided under the following open source license terms:
+ *
+ * The Alfresco Example Content Application is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * The Alfresco Example Content Application is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import { expect } from '@playwright/test';
+import { ApiClientFactory, Utils, test, TrashcanApi, NodesApi } from '@alfresco/playwright-shared';
+
+test.describe('Download from Personal Files', () => {
+  let trashcanApi: TrashcanApi;
+  let nodesApi: NodesApi;
+  let parentId: string;
+
+  const random = Utils.random();
+  const username = `user-${random}`;
+  const parent = `parent-${random}`;
+  const childFile = `childFile-${random}.txt`;
+  const childFolder = `childFolder-${random}`;
+
+  test.beforeAll(async () => {
+    try {
+      const apiClientFactory = new ApiClientFactory();
+      await apiClientFactory.setUpAcaBackend('admin');
+      await apiClientFactory.createUser({ username });
+      trashcanApi = await TrashcanApi.initialize(username, username);
+      nodesApi = await NodesApi.initialize(username, username);
+
+      parentId = (await nodesApi.createFolder(parent)).entry.id;
+      await nodesApi.createFolder(childFolder, parentId);
+      await nodesApi.createFile(childFile, parentId);
+    } catch (error) {
+      console.error(`beforeAll failed: ${error}`);
+    }
+  });
+
+  test.beforeEach(async ({ loginPage }) => {
+    await Utils.tryLoginUser(loginPage, username, username, 'beforeEach failed');
+  });
+
+  test.afterAll(async () => {
+    await Utils.deleteNodesSitesEmptyTrashcan(nodesApi, trashcanApi, 'afterAll failed');
+  });
+
+  test('Download a file', async ({ personalFiles }) => {
+    await personalFiles.dataTable.performClickFolderOrFileToOpen(parent);
+    await personalFiles.dataTable.selectItem(childFile);
+    const [download] = await Promise.all([personalFiles.page.waitForEvent('download'), personalFiles.acaHeader.downloadButton.click()]);
+    expect(download.suggestedFilename()).toBe(childFile);
+  });
+
+  test('Download a folder', async ({ personalFiles }) => {
+    await personalFiles.dataTable.performClickFolderOrFileToOpen(parent);
+    await personalFiles.dataTable.selectItem(childFolder);
+    const [download] = await Promise.all([personalFiles.page.waitForEvent('download'), personalFiles.acaHeader.downloadButton.click()]);
+    const filePath = await download.path();
+    expect(await Utils.verifyZipFileContent(filePath, [childFolder])).toBe(true);
+  });
+
+  test('Download multiple items', async ({ personalFiles }) => {
+    await personalFiles.dataTable.performClickFolderOrFileToOpen(parent);
+    await personalFiles.dataTable.selectMultiItem(childFile, childFolder);
+    const [download] = await Promise.all([personalFiles.page.waitForEvent('download'), personalFiles.acaHeader.downloadButton.click()]);
+    const filePath = await download.path();
+    expect(await Utils.verifyZipFileContent(filePath, [childFile, childFolder])).toBe(true);
+  });
+});
diff --git a/e2e/playwright/upload-download-actions/tsconfig.e2e.adf.json b/e2e/playwright/upload-download-actions/tsconfig.e2e.adf.json
new file mode 100644
index 000000000..87cbcf775
--- /dev/null
+++ b/e2e/playwright/upload-download-actions/tsconfig.e2e.adf.json
@@ -0,0 +1,15 @@
+{
+  "extends": "../../../tsconfig.adf.json",
+  "compilerOptions": {
+    "outDir": "../../out-tsc/e2e",
+    "baseUrl": "./",
+    "module": "commonjs",
+    "target": "es2017",
+    "types": ["jasmine", "jasminewd2", "node"],
+    "skipLibCheck": true,
+    "paths": {
+      "@alfresco/playwright-shared": ["../../../projects/aca-playwright-shared/src/index.ts"]
+    }
+  },
+  "exclude": ["node_modules"]
+}
diff --git a/e2e/playwright/upload-download-actions/tsconfig.e2e.json b/e2e/playwright/upload-download-actions/tsconfig.e2e.json
new file mode 100755
index 000000000..c31798523
--- /dev/null
+++ b/e2e/playwright/upload-download-actions/tsconfig.e2e.json
@@ -0,0 +1,15 @@
+{
+  "extends": "../../../tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../../out-tsc/e2e",
+    "baseUrl": "./",
+    "module": "commonjs",
+    "target": "es2017",
+    "types": ["jasmine", "jasminewd2", "node", "@playwright/test"],
+    "skipLibCheck": true,
+    "paths": {
+      "@alfresco/playwright-shared": ["../../../projects/aca-playwright-shared/src/index.ts"]
+    }
+  },
+  "exclude": ["node_modules"]
+}
diff --git a/e2e/playwright/viewer/src/tests/viewer-action.e2e.ts b/e2e/playwright/viewer/src/tests/viewer-action.e2e.ts
index c3deb981f..8bbc0ef83 100644
--- a/e2e/playwright/viewer/src/tests/viewer-action.e2e.ts
+++ b/e2e/playwright/viewer/src/tests/viewer-action.e2e.ts
@@ -85,7 +85,7 @@ test.describe('viewer action file', () => {
     await personalFiles.dataTable.performClickFolderOrFileToOpen(randomDocxName);
     await personalFiles.viewer.waitForViewerToOpen();
     const downloadPromise = personalFiles.page.waitForEvent('download');
-    await personalFiles.acaHeader.downloadButton.click();
+    await personalFiles.acaHeader.downloadButtonViewer.click();
     const download = await downloadPromise;
     expect(download.suggestedFilename()).toBe(randomDocxName);
   });
@@ -112,7 +112,7 @@ test.describe('viewer action file', () => {
     await personalFiles.matMenu.clickMenuItem('Edit Offline');
 
     const downloadPromise = personalFiles.page.waitForEvent('download');
-    await personalFiles.acaHeader.downloadButton.click();
+    await personalFiles.acaHeader.downloadButtonViewer.click();
     const download = await downloadPromise;
     expect(download.suggestedFilename(), 'File should found in download location').toBe(fileForEditOffline);
     expect(await personalFiles.viewer.isViewerOpened(), 'Viewer is closed after pressing Full screen').toBe(true);
diff --git a/projects/aca-playwright-shared/src/page-objects/components/aca-header.component.ts b/projects/aca-playwright-shared/src/page-objects/components/aca-header.component.ts
index b47c11aa8..f223f7e9f 100644
--- a/projects/aca-playwright-shared/src/page-objects/components/aca-header.component.ts
+++ b/projects/aca-playwright-shared/src/page-objects/components/aca-header.component.ts
@@ -36,7 +36,8 @@ export class AcaHeader extends BaseComponent {
   public searchButton = this.getChild('button[title="Search"]');
   public fullScreenButton = this.getChild('button[id="app.viewer.fullscreen"]');
   public shareButton = this.getChild('button[id="share-action-button"]');
-  public downloadButton = this.getChild('button[id="app.viewer.download"]');
+  public downloadButtonViewer = this.getChild('button[id="app.viewer.download"]');
+  public downloadButton = this.getChild('button[id="app.toolbar.download"]');
   public sharedDownloadButton = this.getChild('button[id="app.viewer.shared.download"]');
 
   constructor(page: Page) {
diff --git a/projects/aca-playwright-shared/src/utils/utils.ts b/projects/aca-playwright-shared/src/utils/utils.ts
index 8050f144d..0a7783e57 100644
--- a/projects/aca-playwright-shared/src/utils/utils.ts
+++ b/projects/aca-playwright-shared/src/utils/utils.ts
@@ -27,6 +27,7 @@ import * as path from 'path';
 import { LoginPage, MyLibrariesPage, PersonalFilesPage, FavoritesLibrariesPage, SearchPage, SharedPage, TrashPage } from '../';
 import { NodesApi, TrashcanApi, SitesApi } from '@alfresco/playwright-shared';
 import { format, subDays, subMonths, endOfMonth } from 'date-fns';
+import StreamZip from 'node-stream-zip';
 
 export class Utils {
   static string257Long = 'x'.repeat(257);
@@ -146,4 +147,26 @@ export class Utils {
 
     return { currentDate: formattedDate, previousDate: formattedDate2 };
   }
+
+  static async verifyZipFileContent(filePath: string, fileOrFolderName: string[]): Promise<boolean> {
+    const zip = new StreamZip({
+      file: filePath,
+      storeEntries: true
+    });
+
+    return new Promise<boolean>((resolve) => {
+      zip.on('ready', () => {
+        const entries = zip.entries();
+        const found = this.isFileOrFolderInEntries(entries, fileOrFolderName);
+        zip.close();
+        resolve(found);
+      });
+    });
+  }
+
+  private static isFileOrFolderInEntries(entries: { [name: string]: StreamZip.ZipEntry }, fileOrFolderName: string[]): boolean {
+    return fileOrFolderName.some((name) => {
+      return Object.keys(entries).some((entry) => entry.includes(name));
+    });
+  }
 }