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.INTERNET"/> | ||||||
|     <uses-permission android:name="android.permission.CAMERA"/> |     <uses-permission android:name="android.permission.CAMERA"/> | ||||||
|     <uses-permission android:name="android.permission.MICROPHONE"/> |     <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> | </manifest> | ||||||
							
								
								
									
										91
									
								
								lib/api.dart
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								lib/api.dart
									
									
									
									
									
								
							| @@ -2,9 +2,11 @@ import 'dart:async'; | |||||||
| import 'dart:convert'; | import 'dart:convert'; | ||||||
| import 'dart:io'; | import 'dart:io'; | ||||||
|  |  | ||||||
|  | import 'package:flutter/foundation.dart'; | ||||||
| import 'package:http/http.dart' as http; | import 'package:http/http.dart' as http; | ||||||
| import 'package:intl/intl.dart'; | import 'package:intl/intl.dart'; | ||||||
|  |  | ||||||
|  | import 'package:open_file/open_file.dart'; | ||||||
| import 'package:flutter/cupertino.dart'; | import 'package:flutter/cupertino.dart'; | ||||||
| import 'package:cached_network_image/cached_network_image.dart'; | import 'package:cached_network_image/cached_network_image.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| @@ -16,6 +18,7 @@ import 'package:inventree/l10.dart'; | |||||||
| import 'package:inventree/inventree/sentry.dart'; | import 'package:inventree/inventree/sentry.dart'; | ||||||
| import 'package:inventree/user_profile.dart'; | import 'package:inventree/user_profile.dart'; | ||||||
| import 'package:inventree/widget/snacks.dart'; | import 'package:inventree/widget/snacks.dart'; | ||||||
|  | import 'package:path_provider/path_provider.dart'; | ||||||
|  |  | ||||||
|  |  | ||||||
| /* | /* | ||||||
| @@ -119,6 +122,8 @@ class InvenTreeAPI { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   String _makeUrl(String url) { |   String _makeUrl(String url) { | ||||||
|  |  | ||||||
|  |     // Strip leading slash | ||||||
|     if (url.startsWith('/')) { |     if (url.startsWith('/')) { | ||||||
|       url = url.substring(1, url.length); |       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 |    * 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() { |   void updateSearchTerm() { | ||||||
|  |  | ||||||
|     print("Search Term: '${_searchTerm}'"); |  | ||||||
|  |  | ||||||
|     _searchTerm = searchController.text; |     _searchTerm = searchController.text; | ||||||
|     _pagingController.refresh(); |     _pagingController.refresh(); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -161,6 +161,9 @@ class _PartAttachmentDisplayState extends RefreshableState<PartAttachmentsWidget | |||||||
|         title: Text(attachment.filename), |         title: Text(attachment.filename), | ||||||
|         subtitle: Text(attachment.comment), |         subtitle: Text(attachment.comment), | ||||||
|         leading: FaIcon(attachment.icon), |         leading: FaIcon(attachment.icon), | ||||||
|  |         onTap: () async { | ||||||
|  |           await attachment.downloadAttachment(); | ||||||
|  |         }, | ||||||
|       )); |       )); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -357,6 +357,13 @@ packages: | |||||||
|       url: "https://pub.dartlang.org" |       url: "https://pub.dartlang.org" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "1.1.0" |     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: |   package_info_plus: | ||||||
|     dependency: "direct main" |     dependency: "direct main" | ||||||
|     description: |     description: | ||||||
| @@ -412,7 +419,7 @@ packages: | |||||||
|       name: path_provider |       name: path_provider | ||||||
|       url: "https://pub.dartlang.org" |       url: "https://pub.dartlang.org" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "2.0.1" |     version: "2.0.2" | ||||||
|   path_provider_linux: |   path_provider_linux: | ||||||
|     dependency: transitive |     dependency: transitive | ||||||
|     description: |     description: | ||||||
|   | |||||||
| @@ -33,9 +33,10 @@ dependencies: | |||||||
|   image_picker: ^0.8.3                    # Select or take photos |   image_picker: ^0.8.3                    # Select or take photos | ||||||
|   file_picker: ^4.0.0                     # Select files from the device |   file_picker: ^4.0.0                     # Select files from the device | ||||||
|   url_launcher: 6.0.9                     # Open link in system browser |   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 |   flutter_markdown: ^0.6.2                # Rendering markdown | ||||||
|   camera:                                 # Camera |   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 |   sembast: ^3.1.0+2                       # NoSQL data storage | ||||||
|   one_context: ^1.1.0                     # Dialogs without requiring context |   one_context: ^1.1.0                     # Dialogs without requiring context | ||||||
|   infinite_scroll_pagination: ^3.1.0      # Let the server do all the work! |   infinite_scroll_pagination: ^3.1.0      # Let the server do all the work! | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user