From 3ccffdab193659d1e38e2a1ce657bf8ece76fb07 Mon Sep 17 00:00:00 2001 From: hunteraraujo Date: Wed, 6 Sep 2023 16:08:51 -0700 Subject: [PATCH] Implement artifact download functionality in Flutter web app Added the downloadArtifact method to the ChatService class, enabling the download of artifacts in the Flutter web application. The function uses the dart:html package to trigger a browser-based file download, allowing users to save artifacts locally. This implementation complements the existing REST API and enhances the user experience. --- frontend/lib/services/chat_service.dart | 26 +++++++++++++++++++++--- frontend/lib/utils/rest_api_utility.dart | 16 +++++++++++++++ frontend/pubspec.lock | 16 +++++++++++++++ frontend/pubspec.yaml | 1 + 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/frontend/lib/services/chat_service.dart b/frontend/lib/services/chat_service.dart index 98f9972d..a24aec4f 100644 --- a/frontend/lib/services/chat_service.dart +++ b/frontend/lib/services/chat_service.dart @@ -1,6 +1,8 @@ import 'dart:io'; +import 'dart:typed_data'; import 'package:auto_gpt_flutter_client/models/step_request_body.dart'; import 'package:auto_gpt_flutter_client/utils/rest_api_utility.dart'; +import 'dart:html' as html; /// Service class for performing chat-related operations. class ChatService { @@ -63,8 +65,26 @@ class ChatService { /// /// [taskId] is the ID of the task. /// [artifactId] is the ID of the artifact. - Future> downloadArtifact( - String taskId, String artifactId) async { - return Future.value({'status': 'Not implemented yet'}); + Future downloadArtifact(String taskId, String artifactId) async { + try { + final Uint8List bytes = + await api.getBinary('agent/tasks/$taskId/artifacts/$artifactId'); + + // Create a blob from the Uint8List + final blob = html.Blob([bytes]); + + // Generate a URL from the Blob + final url = html.Url.createObjectUrlFromBlob(blob); + + // Create an anchor HTML element + final anchor = html.AnchorElement(href: url) + ..setAttribute("download", "artifact_$artifactId") + ..click(); + + // Cleanup: Revoke the object URL + html.Url.revokeObjectUrl(url); + } catch (e) { + throw Exception('An error occurred while downloading the artifact: $e'); + } } } diff --git a/frontend/lib/utils/rest_api_utility.dart b/frontend/lib/utils/rest_api_utility.dart index dde50e17..6884f806 100644 --- a/frontend/lib/utils/rest_api_utility.dart +++ b/frontend/lib/utils/rest_api_utility.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:typed_data'; import 'package:http/http.dart' as http; class RestApiUtility { @@ -32,4 +33,19 @@ class RestApiUtility { throw Exception('Failed to post data'); } } + + Future getBinary(String endpoint) async { + final response = await http.get( + Uri.parse('$_baseUrl/$endpoint'), + headers: {"Content-Type": "application/octet-stream"}, + ); + + if (response.statusCode == 200) { + return response.bodyBytes; + } else if (response.statusCode == 404) { + throw Exception('Resource not found'); + } else { + throw Exception('Failed to load binary data'); + } + } } diff --git a/frontend/pubspec.lock b/frontend/pubspec.lock index 85634a73..7d76dc80 100644 --- a/frontend/pubspec.lock +++ b/frontend/pubspec.lock @@ -41,6 +41,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.17.2" + csslib: + dependency: transitive + description: + name: csslib + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" + url: "https://pub.dev" + source: hosted + version: "1.0.0" cupertino_icons: dependency: "direct main" description: @@ -112,6 +120,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.0" + html: + dependency: "direct main" + description: + name: html + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" + url: "https://pub.dev" + source: hosted + version: "0.15.4" http: dependency: "direct main" description: diff --git a/frontend/pubspec.yaml b/frontend/pubspec.yaml index f546fb0c..ec9a08c0 100644 --- a/frontend/pubspec.yaml +++ b/frontend/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: provider: ^6.0.5 http: ^1.1.0 shared_preferences: ^2.2.1 + dart:html: any dev_dependencies: flutter_test: