From 596d8e91dd358a60da256e3701ef830000ec2043 Mon Sep 17 00:00:00 2001 From: rtviwe Date: Tue, 19 Jul 2022 13:39:14 +0300 Subject: [PATCH 1/5] add missing files --- example/pubspec.lock | 29 +++++++++++++--------- lib/js/upload_worker.js | 53 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 lib/js/upload_worker.js diff --git a/example/pubspec.lock b/example/pubspec.lock index 1d7fbb1..73ed609 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.1" + version: "2.8.2" boolean_selector: dependency: transitive description: @@ -21,7 +21,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" charcode: dependency: transitive description: @@ -42,7 +42,7 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0" + version: "1.16.0" crypto: dependency: transitive description: @@ -70,7 +70,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0" flutter: dependency: "direct main" description: flutter @@ -101,7 +101,7 @@ packages: path: ".." relative: true source: path - version: "0.0.3" + version: "0.0.7" lints: dependency: transitive description: @@ -115,7 +115,14 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" meta: dependency: transitive description: @@ -129,7 +136,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" sky_engine: dependency: transitive description: flutter @@ -141,7 +148,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" stack_trace: dependency: transitive description: @@ -176,7 +183,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.2" + version: "0.4.9" typed_data: dependency: transitive description: @@ -204,7 +211,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.2" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=2.17.0-0 <3.0.0" flutter: ">=1.20.0" diff --git a/lib/js/upload_worker.js b/lib/js/upload_worker.js new file mode 100644 index 0000000..5a6af3e --- /dev/null +++ b/lib/js/upload_worker.js @@ -0,0 +1,53 @@ +self.addEventListener('message', async (event) => { + var method = event.data.method; + var uploadUrl = event.data.uploadUrl; + var data = event.data.data; + var headers = event.data.headers; + uploadFile(method, uploadUrl, data, headers); +}); + +function uploadFile(method, uploadUrl, data, headers) { + var xhr = new XMLHttpRequest(); + var formdata = new FormData(); + var uploadPercent; + + setData(formdata, data); + + xhr.upload.addEventListener('progress', function (d) { + if (d.lengthComputable) { + uploadPercent = Math.floor((d.loaded / d.total) * 100); + postMessage(uploadPercent); + } + }, false); + xhr.onreadystatechange = function () { + if (xhr.readyState == XMLHttpRequest.DONE) { + postMessage("done"); + } + } + + xhr.onload = () => { + postMessage(xhr.response); + }; + + xhr.onerror = function () { + // only triggers if the request couldn't be made at all + postMessage("request failed"); + }; + + xhr.open(method, uploadUrl, true); + setHeaders(xhr, headers); + + xhr.send(formdata); +} + +function setData(formdata, data) { + for (let key in data) { + formdata.append(key, data[key]) + } +} + +function setHeaders(xhr, headers) { + for (let key in headers) { + xhr.setRequestHeader(key, headers[key]) + } +} From 4902f142ea309da45fbbc5ce70061cb384cfd1db Mon Sep 17 00:00:00 2001 From: rtviwe Date: Tue, 19 Jul 2022 15:18:51 +0300 Subject: [PATCH 2/5] fixes --- example/lib/main.dart | 1 + example/web/upload_worker.js | 53 -------------------------------- lib/src/large_file_uploader.dart | 36 ++++++++++++++++------ 3 files changed, 27 insertions(+), 63 deletions(-) delete mode 100644 example/web/upload_worker.js diff --git a/example/lib/main.dart b/example/lib/main.dart index 0e6a5f4..e58ab0c 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,3 +1,4 @@ +// ignore: avoid_web_libraries_in_flutter import 'dart:html' as html; import 'package:flutter/material.dart'; diff --git a/example/web/upload_worker.js b/example/web/upload_worker.js deleted file mode 100644 index eb35bdb..0000000 --- a/example/web/upload_worker.js +++ /dev/null @@ -1,53 +0,0 @@ -self.addEventListener('message', async (event) => { - var method = event.data.method; - var uploadUrl = event.data.uploadUrl; - var data = event.data.data; - var headers = event.data.headers; - uploadFile(method, uploadUrl, data, headers); -}); - -function uploadFile(method, uploadUrl, data, headers) { - var xhr = new XMLHttpRequest(); - var formdata = new FormData(); - var uploadPercent; - - setData(formdata, data); - - xhr.upload.addEventListener('progress', function (d) { - if (d.lengthComputable) { - uploadPercent = Math.floor((d.loaded / d.total) * 100); - postMessage(uploadPercent); - } - }, false); - xhr.onreadystatechange = function () { - if (xhr.readyState == XMLHttpRequest.DONE) { - postMessage("done"); - } - } - - xhr.onload = () => { - postMessage(xhr.response); - }; - - xhr.onerror = function () { - // only triggers if the request couldn't be made at all - postMessage("request failed"); - }; - - xhr.open(method, uploadUrl, true); - setHeaders(xhr, headers); - - xhr.send(formdata); -} - -function setData(formdata, data) { - for (let key in data) { - formdata.append(key, data[key]) - } -} - -function setHeaders(xhr, headers) { - for (let key in headers) { - xhr.setRequestHeader(key, headers[key]) - } -} \ No newline at end of file diff --git a/lib/src/large_file_uploader.dart b/lib/src/large_file_uploader.dart index 4f76451..732b2f5 100644 --- a/lib/src/large_file_uploader.dart +++ b/lib/src/large_file_uploader.dart @@ -27,6 +27,7 @@ class LargeFileUploader { String method = 'POST', FileTypes type = FileTypes.file, String? customFileType, + bool allowMultiple = false, required String uploadUrl, Map? data, Map? headers, @@ -40,10 +41,22 @@ class LargeFileUploader { pick( type: type, customFileType: customFileType, + allowMultiple: allowMultiple, callback: (file) { data ??= {}; data!["file"] = file; - upload(uploadUrl: uploadUrl, onSendProgress: onSendProgress, data: data!); + upload( + method: method, + uploadUrl: uploadUrl, + data: data!, + headers: headers, + onSendProgress: onSendProgress, + fakePreProcessMaxProgress: fakePreProcessMaxProgress, + fakePreProcessProgressPeriodInMillisecond: fakePreProcessProgressPeriodInMillisecond, + onSendWithFakePreProcessProgress: onSendWithFakePreProcessProgress, + onFailure: onFailure, + onComplete: onComplete, + ); }, ); } @@ -51,11 +64,12 @@ class LargeFileUploader { void pick({ FileTypes type = FileTypes.file, String? customFileType, + bool allowMultiple = false, required OnFileSelectedListener callback, }) { html.FileUploadInputElement fileUploadInputElement = html.FileUploadInputElement(); fileUploadInputElement.accept = customFileType ?? type.value; - fileUploadInputElement.multiple = false; + fileUploadInputElement.multiple = allowMultiple; fileUploadInputElement.click(); fileUploadInputElement.onChange.listen((_) { @@ -66,11 +80,11 @@ class LargeFileUploader { } void upload({ + String method = 'POST', required String uploadUrl, - required UploadProgressListener onSendProgress, required Map data, - String method = 'POST', Map? headers, + required UploadProgressListener onSendProgress, int fakePreProcessMaxProgress = 30, int fakePreProcessProgressPeriodInMillisecond = 500, UploadProgressListener? onSendWithFakePreProcessProgress, @@ -96,12 +110,14 @@ class LargeFileUploader { } _worker.onMessage.listen((data) { - _handleCallbacks(data.data, - onSendProgress: onSendProgress, - fakePreProcessMaxProgress: fakePreProcessMaxProgress, - onSendWithFakePreProcessProgress: onSendWithFakePreProcessProgress, - onFailure: onFailure, - onComplete: onComplete); + _handleCallbacks( + data.data, + onSendProgress: onSendProgress, + fakePreProcessMaxProgress: fakePreProcessMaxProgress, + onSendWithFakePreProcessProgress: onSendWithFakePreProcessProgress, + onFailure: onFailure, + onComplete: onComplete, + ); }); } From 69d8ad19b28ab5726f779bea9030720d4cb248f3 Mon Sep 17 00:00:00 2001 From: rtviwe Date: Tue, 19 Jul 2022 16:32:19 +0300 Subject: [PATCH 3/5] cancel stream subscription --- lib/src/large_file_uploader.dart | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/src/large_file_uploader.dart b/lib/src/large_file_uploader.dart index 732b2f5..0a44f54 100644 --- a/lib/src/large_file_uploader.dart +++ b/lib/src/large_file_uploader.dart @@ -23,6 +23,8 @@ class LargeFileUploader { Timer? _timer; int _fakeProgress = 0; + StreamSubscription? _streamSubscription; + void selectFileAndUpload({ String method = 'POST', FileTypes type = FileTypes.file, @@ -90,7 +92,7 @@ class LargeFileUploader { UploadProgressListener? onSendWithFakePreProcessProgress, UploadFailureListener? onFailure, UploadCompleteListener? onComplete, - }) { + }) async { _worker.postMessage({ 'method': method, 'uploadUrl': uploadUrl, @@ -109,7 +111,7 @@ class LargeFileUploader { }); } - _worker.onMessage.listen((data) { + _streamSubscription = _worker.onMessage.listen((data) { _handleCallbacks( data.data, onSendProgress: onSendProgress, @@ -145,6 +147,7 @@ class LargeFileUploader { onSendWithFakePreProcessProgress?.call(100); _disposeTimerAndFakeProgress(); onComplete?.call(data); + _streamSubscription?.cancel(); } } From 8373181e35c7cc9c043131c0d08450717695e713 Mon Sep 17 00:00:00 2001 From: rtviwe Date: Tue, 19 Jul 2022 16:43:29 +0300 Subject: [PATCH 4/5] add id and multiple files --- example/lib/main.dart | 3 ++- lib/src/large_file_uploader.dart | 23 ++++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index e58ab0c..abfd4d5 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -107,9 +107,10 @@ class _UploadExampleState extends State { if (pickedFile != null && pickedThumbnail != null) { _largeFileUploader.upload( uploadUrl: url, + id: '1', headers: {"Authorization": "Bearer $accessToken"}, data: {"title": "Sample Title", "thumbnail": pickedThumbnail, "file": pickedFile}, - onSendProgress: (progress) => debugPrint(progress.toString()), + onSendProgress: (progress, id) => debugPrint('$id: $progress'), onComplete: (response) => debugPrint(response.toString()), ); diff --git a/lib/src/large_file_uploader.dart b/lib/src/large_file_uploader.dart index 0a44f54..f3f856d 100644 --- a/lib/src/large_file_uploader.dart +++ b/lib/src/large_file_uploader.dart @@ -4,7 +4,7 @@ import 'package:large_file_uploader/src/enum/file_types.dart'; import 'package:universal_html/html.dart' as html; /// Callback exposing currently upload progress. -typedef UploadProgressListener = Function(int progress); +typedef UploadProgressListener = Function(int progress, String id); /// Callback exposing upload fail event. typedef UploadFailureListener = Function(); @@ -27,6 +27,7 @@ class LargeFileUploader { void selectFileAndUpload({ String method = 'POST', + required String id, FileTypes type = FileTypes.file, String? customFileType, bool allowMultiple = false, @@ -49,6 +50,7 @@ class LargeFileUploader { data!["file"] = file; upload( method: method, + id: id, uploadUrl: uploadUrl, data: data!, headers: headers, @@ -76,13 +78,16 @@ class LargeFileUploader { fileUploadInputElement.onChange.listen((_) { if (fileUploadInputElement.files != null) { - callback.call(fileUploadInputElement.files!.first); + for (final file in fileUploadInputElement.files!) { + callback.call(file); + } } }); } void upload({ String method = 'POST', + required String id, required String uploadUrl, required Map data, Map? headers, @@ -104,7 +109,7 @@ class LargeFileUploader { _timer = Timer.periodic(Duration(milliseconds: fakePreProcessProgressPeriodInMillisecond), (Timer timer) { if (_fakeProgress != fakePreProcessMaxProgress) { _fakeProgress++; - onSendWithFakePreProcessProgress.call(_fakeProgress); + onSendWithFakePreProcessProgress.call(_fakeProgress, 'fake'); } else { _disposeTimerAndFakeProgress(); } @@ -114,6 +119,7 @@ class LargeFileUploader { _streamSubscription = _worker.onMessage.listen((data) { _handleCallbacks( data.data, + id: id, onSendProgress: onSendProgress, fakePreProcessMaxProgress: fakePreProcessMaxProgress, onSendWithFakePreProcessProgress: onSendWithFakePreProcessProgress, @@ -125,6 +131,7 @@ class LargeFileUploader { void _handleCallbacks( data, { + required String id, required UploadProgressListener onSendProgress, required int fakePreProcessMaxProgress, UploadProgressListener? onSendWithFakePreProcessProgress, @@ -134,17 +141,19 @@ class LargeFileUploader { if (data == null) return; if (data is int) { - onSendProgress.call(data); + onSendProgress.call(data, id); if (data != 0) { _disposeTimerAndFakeProgress(); - onSendWithFakePreProcessProgress - ?.call((fakePreProcessMaxProgress + (data * ((100 - fakePreProcessMaxProgress) / 100))).toInt()); + onSendWithFakePreProcessProgress?.call( + (fakePreProcessMaxProgress + (data * ((100 - fakePreProcessMaxProgress) / 100))).toInt(), + id, + ); } } else if (data.toString() == 'request failed') { _disposeTimerAndFakeProgress(); onFailure?.call(); } else { - onSendWithFakePreProcessProgress?.call(100); + onSendWithFakePreProcessProgress?.call(100, id); _disposeTimerAndFakeProgress(); onComplete?.call(data); _streamSubscription?.cancel(); From 52942e33c1fab365158f52be416ef2302c60d261 Mon Sep 17 00:00:00 2001 From: rtviwe Date: Tue, 19 Jul 2022 16:45:33 +0300 Subject: [PATCH 5/5] use name instead of id --- example/lib/main.dart | 2 +- lib/src/large_file_uploader.dart | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index abfd4d5..88ef145 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -107,7 +107,7 @@ class _UploadExampleState extends State { if (pickedFile != null && pickedThumbnail != null) { _largeFileUploader.upload( uploadUrl: url, - id: '1', + name: '1', headers: {"Authorization": "Bearer $accessToken"}, data: {"title": "Sample Title", "thumbnail": pickedThumbnail, "file": pickedFile}, onSendProgress: (progress, id) => debugPrint('$id: $progress'), diff --git a/lib/src/large_file_uploader.dart b/lib/src/large_file_uploader.dart index f3f856d..f0ddf70 100644 --- a/lib/src/large_file_uploader.dart +++ b/lib/src/large_file_uploader.dart @@ -27,7 +27,6 @@ class LargeFileUploader { void selectFileAndUpload({ String method = 'POST', - required String id, FileTypes type = FileTypes.file, String? customFileType, bool allowMultiple = false, @@ -50,7 +49,7 @@ class LargeFileUploader { data!["file"] = file; upload( method: method, - id: id, + name: file.name, uploadUrl: uploadUrl, data: data!, headers: headers, @@ -87,7 +86,7 @@ class LargeFileUploader { void upload({ String method = 'POST', - required String id, + required String name, required String uploadUrl, required Map data, Map? headers, @@ -119,7 +118,7 @@ class LargeFileUploader { _streamSubscription = _worker.onMessage.listen((data) { _handleCallbacks( data.data, - id: id, + name: name, onSendProgress: onSendProgress, fakePreProcessMaxProgress: fakePreProcessMaxProgress, onSendWithFakePreProcessProgress: onSendWithFakePreProcessProgress, @@ -131,7 +130,7 @@ class LargeFileUploader { void _handleCallbacks( data, { - required String id, + required String name, required UploadProgressListener onSendProgress, required int fakePreProcessMaxProgress, UploadProgressListener? onSendWithFakePreProcessProgress, @@ -141,19 +140,19 @@ class LargeFileUploader { if (data == null) return; if (data is int) { - onSendProgress.call(data, id); + onSendProgress.call(data, name); if (data != 0) { _disposeTimerAndFakeProgress(); onSendWithFakePreProcessProgress?.call( (fakePreProcessMaxProgress + (data * ((100 - fakePreProcessMaxProgress) / 100))).toInt(), - id, + name, ); } } else if (data.toString() == 'request failed') { _disposeTimerAndFakeProgress(); onFailure?.call(); } else { - onSendWithFakePreProcessProgress?.call(100, id); + onSendWithFakePreProcessProgress?.call(100, name); _disposeTimerAndFakeProgress(); onComplete?.call(data); _streamSubscription?.cancel();