From bc9c7a06c8f95b7a6f72075693e7f5b6ae6f4226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20B=C3=B6sche?= Date: Tue, 13 Jan 2026 23:10:47 +0100 Subject: [PATCH] Fix download: fetch file with auth header, create blob for proper download --- b0esche_cloud/lib/pages/file_explorer.dart | 41 +++++++++++++++++----- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/b0esche_cloud/lib/pages/file_explorer.dart b/b0esche_cloud/lib/pages/file_explorer.dart index 3e54b22..d85f893 100644 --- a/b0esche_cloud/lib/pages/file_explorer.dart +++ b/b0esche_cloud/lib/pages/file_explorer.dart @@ -1,9 +1,11 @@ import 'dart:ui'; +import 'dart:js_interop'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:file_picker/file_picker.dart' hide FileType; import 'package:path/path.dart' as p; import 'package:web/web.dart' as web; +import 'package:http/http.dart' as http; import '../blocs/file_browser/file_browser_bloc.dart'; import '../blocs/file_browser/file_browser_event.dart'; import '../blocs/file_browser/file_browser_state.dart'; @@ -303,14 +305,14 @@ class _FileExplorerState extends State { const SizedBox(width: 12), Expanded( child: Text( - 'Preparing download: ${file.name}', + 'Downloading: ${file.name}', overflow: TextOverflow.ellipsis, style: const TextStyle(color: AppTheme.primaryText), ), ), ], ), - duration: const Duration(seconds: 3), + duration: const Duration(days: 1), // Keep showing until dismissed backgroundColor: AppTheme.primaryBackground, ), ); @@ -335,15 +337,38 @@ class _FileExplorerState extends State { file.path, ); - // Build full URL with token for authentication (anchor elements can't send headers) - final fullUrl = - '${fileService.baseUrl}$downloadUrl&token=${Uri.encodeComponent(token)}'; + // Build full URL + final fullUrl = '${fileService.baseUrl}$downloadUrl'; - // Trigger download via anchor element + // Fetch file with authentication header + final response = await http.get( + Uri.parse(fullUrl), + headers: {'Authorization': 'Bearer $token'}, + ); + + if (response.statusCode != 200) { + throw Exception('Failed to download: ${response.statusCode}'); + } + + // Create blob and trigger download + final bytes = response.bodyBytes; + final blob = web.Blob( + [bytes.toJS].toJS, + web.BlobPropertyBag(type: response.headers['content-type'] ?? 'application/octet-stream'), + ); + final blobUrl = web.URL.createObjectURL(blob); + + // Create anchor and trigger download final anchor = web.HTMLAnchorElement() - ..href = fullUrl - ..download = file.name; + ..href = blobUrl + ..download = file.name + ..style.display = 'none'; + web.document.body?.appendChild(anchor); anchor.click(); + + // Cleanup + web.document.body?.removeChild(anchor); + web.URL.revokeObjectURL(blobUrl); // Dismiss preparing snackbar and show success snackController?.close();