Skip to content

Commit 9e49783

Browse files
authored
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
1 parent 43e3075 commit 9e49783

File tree

3 files changed

+17
-18
lines changed

3 files changed

+17
-18
lines changed

e2e/src/web/specs/shared-link.e2e-spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,15 @@ test.describe('Shared Links', () => {
4848
await page.waitForSelector('[data-group] svg');
4949
await page.getByRole('checkbox').click();
5050
await page.getByRole('button', { name: 'Download' }).click();
51-
await page.getByText('DOWNLOADING', { exact: true }).waitFor();
51+
await page.waitForEvent('download');
5252
});
5353

5454
test('download all from shared link', async ({ page }) => {
5555
await page.goto(`/share/${sharedLink.key}`);
5656
await page.getByRole('heading', { name: 'Test Album' }).waitFor();
5757
await page.getByRole('button', { name: 'Download' }).click();
5858
await page.getByText('DOWNLOADING', { exact: true }).waitFor();
59+
await page.waitForEvent('download');
5960
});
6061

6162
test('enter password for a shared link', async ({ page }) => {

web/src/lib/stores/download.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const update = (key: string, value: Partial<DownloadProgress> | null) => {
2929
const item = newState[key];
3030
Object.assign(item, value);
3131
item.percentage = Math.min(Math.floor((item.progress / item.total) * 100), 100);
32+
newState[key] = { ...item };
3233

3334
return newState;
3435
});

web/src/lib/utils/asset-utils.ts

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,18 @@ export const downloadBlob = (data: Blob, filename: string) => {
162162
URL.revokeObjectURL(url);
163163
};
164164

165+
export const downloadUrl = (url: string, filename: string) => {
166+
const anchor = document.createElement('a');
167+
anchor.href = url;
168+
anchor.download = filename;
169+
170+
document.body.append(anchor);
171+
anchor.click();
172+
anchor.remove();
173+
174+
URL.revokeObjectURL(url);
175+
};
176+
165177
export const downloadArchive = async (fileName: string, options: Omit<DownloadInfoDto, 'archiveSize'>) => {
166178
const $preferences = get<UserPreferencesResponseDto | undefined>(preferences);
167179
const dto = { ...options, archiveSize: $preferences?.download.archiveSize };
@@ -238,33 +250,18 @@ export const downloadFile = async (asset: AssetResponseDto) => {
238250
}
239251
}
240252

241-
for (const { filename, id, size } of assets) {
242-
const downloadKey = filename;
243-
253+
for (const { filename, id } of assets) {
244254
try {
245-
const abort = new AbortController();
246-
downloadManager.add(downloadKey, size, abort);
247255
const key = getKey();
248256

249257
notificationController.show({
250258
type: NotificationType.Info,
251259
message: $t('downloading_asset_filename', { values: { filename: asset.originalFileName } }),
252260
});
253261

254-
// TODO use sdk once it supports progress events
255-
const { data } = await downloadRequest({
256-
method: 'GET',
257-
url: getBaseUrl() + `/assets/${id}/original` + (key ? `?key=${key}` : ''),
258-
signal: abort.signal,
259-
onDownloadProgress: (event) => downloadManager.update(downloadKey, event.loaded, event.total),
260-
});
261-
262-
downloadBlob(data, filename);
262+
downloadUrl(getBaseUrl() + `/assets/${id}/original` + (key ? `?key=${key}` : ''), filename);
263263
} catch (error) {
264264
handleError(error, $t('errors.error_downloading', { values: { filename } }));
265-
downloadManager.clear(downloadKey);
266-
} finally {
267-
setTimeout(() => downloadManager.clear(downloadKey), 5000);
268265
}
269266
}
270267
};

0 commit comments

Comments
 (0)