diff --git a/web/src/lib/components/maintenance/MaintenanceBackupsList.svelte b/web/src/lib/components/maintenance/MaintenanceBackupsList.svelte
index 699d6de74f..c8fe5b30d1 100644
--- a/web/src/lib/components/maintenance/MaintenanceBackupsList.svelte
+++ b/web/src/lib/components/maintenance/MaintenanceBackupsList.svelte
@@ -1,10 +1,12 @@
diff --git a/web/src/lib/services/database-backups.service.ts b/web/src/lib/services/database-backups.service.ts
index bd0292cfbb..540d532e92 100644
--- a/web/src/lib/services/database-backups.service.ts
+++ b/web/src/lib/services/database-backups.service.ts
@@ -1,7 +1,36 @@
+import { uploadRequest } from '$lib/utils';
+import { openFilePicker } from '$lib/utils/file-uploader';
import { handleError } from '$lib/utils/handle-error';
import { getFormatter } from '$lib/utils/i18n';
-import { deleteDatabaseBackup, MaintenanceAction, setMaintenanceMode } from '@immich/sdk';
-import { modalManager } from '@immich/ui';
+import {
+ deleteDatabaseBackup,
+ getBaseUrl,
+ MaintenanceAction,
+ setMaintenanceMode,
+ type DatabaseBackupUploadDto,
+} from '@immich/sdk';
+import { modalManager, type ActionItem } from '@immich/ui';
+import { mdiDownload, mdiTrashCanOutline } from '@mdi/js';
+import type { MessageFormatter } from 'svelte-i18n';
+
+export const getDatabaseBackupActions = ($t: MessageFormatter, filename: string, remove: () => void) => {
+ const Download: ActionItem = {
+ title: $t('download'),
+ icon: mdiDownload,
+ onAction() {
+ void handleDownloadDatabaseBackup(filename);
+ },
+ };
+
+ const Delete: ActionItem = {
+ title: $t('delete'),
+ icon: mdiTrashCanOutline,
+ color: 'danger',
+ onAction: remove,
+ };
+
+ return { Download, Delete };
+};
export const handleRestoreDatabaseBackup = async (filename: string) => {
const $t = await getFormatter();
@@ -51,3 +80,33 @@ export const handleDeleteDatabaseBackup = async (...filenames: string[]) => {
handleError(error, $t('admin.maintenance_delete_error'));
}
};
+
+export const handleDownloadDatabaseBackup = (filename: string) => {
+ location.href = getBaseUrl() + '/admin/database-backups/' + filename;
+};
+
+export const handleUploadDatabaseBackup = async (progressFn?: (progress: number) => void) => {
+ const $t = await getFormatter();
+
+ try {
+ const [file] = await openFilePicker({ multiple: false });
+ const formData = new FormData();
+ formData.append('file', file);
+
+ await uploadRequest({
+ url: getBaseUrl() + '/admin/database-backups/upload',
+ data: formData,
+ onUploadProgress(event) {
+ progressFn?.(event.loaded / event.total);
+ },
+ });
+
+ progressFn?.(1);
+
+ return true;
+ } catch (error) {
+ handleError(error, $t('admin.maintenance_upload_backup_error'));
+ } finally {
+ progressFn?.(-1);
+ }
+};