feat: use browser download manager for single file downloads (#17507)

* Fix download panel reactivity

* Directly download individual files without buffering in memory

* Fix shared link e2e download tests
This commit is contained in:
Rudhra Raveendran 2025-04-10 07:13:50 -07:00 committed by GitHub
parent 43e3075f93
commit 9e49783e49
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 17 additions and 18 deletions

View File

@ -48,7 +48,7 @@ test.describe('Shared Links', () => {
await page.waitForSelector('[data-group] svg');
await page.getByRole('checkbox').click();
await page.getByRole('button', { name: 'Download' }).click();
await page.getByText('DOWNLOADING', { exact: true }).waitFor();
await page.waitForEvent('download');
});
test('download all from shared link', async ({ page }) => {
@ -56,6 +56,7 @@ test.describe('Shared Links', () => {
await page.getByRole('heading', { name: 'Test Album' }).waitFor();
await page.getByRole('button', { name: 'Download' }).click();
await page.getByText('DOWNLOADING', { exact: true }).waitFor();
await page.waitForEvent('download');
});
test('enter password for a shared link', async ({ page }) => {

View File

@ -29,6 +29,7 @@ const update = (key: string, value: Partial<DownloadProgress> | null) => {
const item = newState[key];
Object.assign(item, value);
item.percentage = Math.min(Math.floor((item.progress / item.total) * 100), 100);
newState[key] = { ...item };
return newState;
});

View File

@ -162,6 +162,18 @@ export const downloadBlob = (data: Blob, filename: string) => {
URL.revokeObjectURL(url);
};
export const downloadUrl = (url: string, filename: string) => {
const anchor = document.createElement('a');
anchor.href = url;
anchor.download = filename;
document.body.append(anchor);
anchor.click();
anchor.remove();
URL.revokeObjectURL(url);
};
export const downloadArchive = async (fileName: string, options: Omit<DownloadInfoDto, 'archiveSize'>) => {
const $preferences = get<UserPreferencesResponseDto | undefined>(preferences);
const dto = { ...options, archiveSize: $preferences?.download.archiveSize };
@ -238,12 +250,8 @@ export const downloadFile = async (asset: AssetResponseDto) => {
}
}
for (const { filename, id, size } of assets) {
const downloadKey = filename;
for (const { filename, id } of assets) {
try {
const abort = new AbortController();
downloadManager.add(downloadKey, size, abort);
const key = getKey();
notificationController.show({
@ -251,20 +259,9 @@ export const downloadFile = async (asset: AssetResponseDto) => {
message: $t('downloading_asset_filename', { values: { filename: asset.originalFileName } }),
});
// TODO use sdk once it supports progress events
const { data } = await downloadRequest({
method: 'GET',
url: getBaseUrl() + `/assets/${id}/original` + (key ? `?key=${key}` : ''),
signal: abort.signal,
onDownloadProgress: (event) => downloadManager.update(downloadKey, event.loaded, event.total),
});
downloadBlob(data, filename);
downloadUrl(getBaseUrl() + `/assets/${id}/original` + (key ? `?key=${key}` : ''), filename);
} catch (error) {
handleError(error, $t('errors.error_downloading', { values: { filename } }));
downloadManager.clear(downloadKey);
} finally {
setTimeout(() => downloadManager.clear(downloadKey), 5000);
}
}
};