mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-30 21:05:42 +00:00 
			
		
		
		
	Download attachments and open
- Uses package "open_file"
This commit is contained in:
		| @@ -52,6 +52,7 @@ | ||||
|     <uses-permission android:name="android.permission.INTERNET"/> | ||||
|     <uses-permission android:name="android.permission.CAMERA"/> | ||||
|     <uses-permission android:name="android.permission.MICROPHONE"/> | ||||
|  | ||||
|     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | ||||
|     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | ||||
|  | ||||
| </manifest> | ||||
							
								
								
									
										91
									
								
								lib/api.dart
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								lib/api.dart
									
									
									
									
									
								
							| @@ -2,9 +2,11 @@ import 'dart:async'; | ||||
| import 'dart:convert'; | ||||
| import 'dart:io'; | ||||
|  | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:http/http.dart' as http; | ||||
| import 'package:intl/intl.dart'; | ||||
|  | ||||
| import 'package:open_file/open_file.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:cached_network_image/cached_network_image.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| @@ -16,6 +18,7 @@ import 'package:inventree/l10.dart'; | ||||
| import 'package:inventree/inventree/sentry.dart'; | ||||
| import 'package:inventree/user_profile.dart'; | ||||
| import 'package:inventree/widget/snacks.dart'; | ||||
| import 'package:path_provider/path_provider.dart'; | ||||
|  | ||||
|  | ||||
| /* | ||||
| @@ -119,6 +122,8 @@ class InvenTreeAPI { | ||||
|   } | ||||
|  | ||||
|   String _makeUrl(String url) { | ||||
|  | ||||
|     // Strip leading slash | ||||
|     if (url.startsWith('/')) { | ||||
|       url = url.substring(1, url.length); | ||||
|     } | ||||
| @@ -469,6 +474,92 @@ class InvenTreeAPI { | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Download a file from the given URL | ||||
|    */ | ||||
|   Future<void> downloadFile(String url, {bool openOnDownload = true}) async { | ||||
|  | ||||
|     showSnackIcon( | ||||
|       L10().downloading, | ||||
|       icon: FontAwesomeIcons.download, | ||||
|       success: true | ||||
|     ); | ||||
|  | ||||
|     // Find the local downlods directory | ||||
|     final Directory dir = await getTemporaryDirectory(); | ||||
|  | ||||
|     String filename = url.split("/").last; | ||||
|  | ||||
|     String local_path = dir.path + "/" + filename; | ||||
|  | ||||
|     Uri? _uri = Uri.tryParse(makeUrl(url)); | ||||
|  | ||||
|     if (_uri == null) { | ||||
|       showServerError(L10().invalidHost, L10().invalidHostDetails); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     if (_uri.host.isEmpty) { | ||||
|       showServerError(L10().invalidHost, L10().invalidHostDetails); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     HttpClientRequest? _request; | ||||
|  | ||||
|     var client = createClient(true); | ||||
|  | ||||
|     // Attempt to open a connection to the server | ||||
|     try { | ||||
|       _request = await client.openUrl("GET", _uri).timeout(Duration(seconds: 10)); | ||||
|  | ||||
|       // Set headers | ||||
|       _request.headers.set(HttpHeaders.authorizationHeader, _authorizationHeader()); | ||||
|       _request.headers.set(HttpHeaders.acceptHeader, 'application/json'); | ||||
|       _request.headers.set(HttpHeaders.contentTypeHeader, 'application/json'); | ||||
|       _request.headers.set(HttpHeaders.acceptLanguageHeader, Intl.getCurrentLocale()); | ||||
|  | ||||
|     } on SocketException catch (error) { | ||||
|       print("SocketException at ${url}: ${error.toString()}"); | ||||
|       showServerError(L10().connectionRefused, error.toString()); | ||||
|       return; | ||||
|     } on TimeoutException { | ||||
|       print("TimeoutException at ${url}"); | ||||
|       showTimeoutError(); | ||||
|       return; | ||||
|     } catch (error, stackTrace) { | ||||
|       print("Server error at ${url}: ${error.toString()}"); | ||||
|       showServerError(L10().serverError, error.toString()); | ||||
|       sentryReportError(error, stackTrace); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|       final response = await _request.close(); | ||||
|  | ||||
|       if (response.statusCode == 200) { | ||||
|         var bytes = await consolidateHttpClientResponseBytes(response); | ||||
|  | ||||
|         File localFile = File(local_path); | ||||
|  | ||||
|         await localFile.writeAsBytes(bytes); | ||||
|  | ||||
|         if (openOnDownload) { | ||||
|           OpenFile.open(local_path); | ||||
|         } | ||||
|       } else { | ||||
|         showStatusCodeError(response.statusCode); | ||||
|       } | ||||
|     } on SocketException catch (error) { | ||||
|       showServerError(L10().connectionRefused, error.toString()); | ||||
|     } on TimeoutException { | ||||
|       showTimeoutError(); | ||||
|     } catch (error, stackTrace) { | ||||
|       print("Error downloading image:"); | ||||
|       print(error.toString()); | ||||
|       showServerError(L10().downloadError, error.toString()); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* | ||||
|    * Upload a file to the given URL | ||||
|    */ | ||||
|   | ||||
| @@ -526,6 +526,12 @@ class InvenTreeAttachment extends InvenTreeModel { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   Future<void> downloadAttachment() async { | ||||
|  | ||||
|     await InvenTreeAPI().downloadFile(attachment); | ||||
|  | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								lib/l10n
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								lib/l10n
									
									
									
									
									
								
							 Submodule lib/l10n updated: faec97124b...e6b7dd53bc
									
								
							| @@ -510,8 +510,6 @@ class _PaginatedPartListState extends State<PaginatedPartList> { | ||||
|  | ||||
|   void updateSearchTerm() { | ||||
|  | ||||
|     print("Search Term: '${_searchTerm}'"); | ||||
|  | ||||
|     _searchTerm = searchController.text; | ||||
|     _pagingController.refresh(); | ||||
|   } | ||||
|   | ||||
| @@ -161,6 +161,9 @@ class _PartAttachmentDisplayState extends RefreshableState<PartAttachmentsWidget | ||||
|         title: Text(attachment.filename), | ||||
|         subtitle: Text(attachment.comment), | ||||
|         leading: FaIcon(attachment.icon), | ||||
|         onTap: () async { | ||||
|           await attachment.downloadAttachment(); | ||||
|         }, | ||||
|       )); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -357,6 +357,13 @@ packages: | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "1.1.0" | ||||
|   open_file: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
|       name: open_file | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "3.2.1" | ||||
|   package_info_plus: | ||||
|     dependency: "direct main" | ||||
|     description: | ||||
| @@ -412,7 +419,7 @@ packages: | ||||
|       name: path_provider | ||||
|       url: "https://pub.dartlang.org" | ||||
|     source: hosted | ||||
|     version: "2.0.1" | ||||
|     version: "2.0.2" | ||||
|   path_provider_linux: | ||||
|     dependency: transitive | ||||
|     description: | ||||
|   | ||||
| @@ -33,9 +33,10 @@ dependencies: | ||||
|   image_picker: ^0.8.3                    # Select or take photos | ||||
|   file_picker: ^4.0.0                     # Select files from the device | ||||
|   url_launcher: 6.0.9                     # Open link in system browser | ||||
|   open_file: 3.2.1                        # Open local files | ||||
|   flutter_markdown: ^0.6.2                # Rendering markdown | ||||
|   camera:                                 # Camera | ||||
|   path_provider: 2.0.1                    # Local file storage | ||||
|   path_provider: 2.0.2                    # Local file storage | ||||
|   sembast: ^3.1.0+2                       # NoSQL data storage | ||||
|   one_context: ^1.1.0                     # Dialogs without requiring context | ||||
|   infinite_scroll_pagination: ^3.1.0      # Let the server do all the work! | ||||
|   | ||||
		Reference in New Issue
	
	Block a user