From fe609eb6a5e9d5303b2822743e2bf65a82977539 Mon Sep 17 00:00:00 2001 From: Shehab Mohamed Date: Wed, 14 Aug 2024 04:29:22 +0300 Subject: [PATCH 01/11] Add ability to change [FileMode] of the download by introducing [DioFileMode] --- dio/lib/dio.dart | 3 ++- dio/lib/src/dio.dart | 7 +++++++ dio/lib/src/dio/dio_for_native.dart | 9 ++++++++- dio/lib/src/dio_file_mode.dart | 24 +++++++++++++++++++++++ dio/lib/src/dio_mixin.dart | 3 +++ plugins/web_adapter/lib/src/dio_impl.dart | 1 + 6 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 dio/lib/src/dio_file_mode.dart diff --git a/dio/lib/dio.dart b/dio/lib/dio.dart index eda699923..db5c49ccb 100644 --- a/dio/lib/dio.dart +++ b/dio/lib/dio.dart @@ -9,6 +9,7 @@ export 'src/adapter.dart'; export 'src/cancel_token.dart'; export 'src/dio.dart'; export 'src/dio_exception.dart'; +export 'src/dio_file_mode.dart'; export 'src/dio_mixin.dart' hide InterceptorState, InterceptorResultType; export 'src/form_data.dart'; export 'src/headers.dart'; @@ -18,4 +19,4 @@ export 'src/options.dart'; export 'src/parameter.dart'; export 'src/redirect_record.dart'; export 'src/response.dart'; -export 'src/transformer.dart'; +export 'src/transformer.dart'; \ No newline at end of file diff --git a/dio/lib/src/dio.dart b/dio/lib/src/dio.dart index 321398745..084847b72 100644 --- a/dio/lib/src/dio.dart +++ b/dio/lib/src/dio.dart @@ -5,6 +5,7 @@ import 'cancel_token.dart'; import 'dio/dio_for_native.dart' if (dart.library.js_interop) 'dio/dio_for_browser.dart' if (dart.library.html) 'dio/dio_for_browser.dart'; +import 'dio_file_mode.dart'; import 'dio_mixin.dart'; import 'headers.dart'; import 'options.dart'; @@ -209,6 +210,9 @@ abstract class Dio { /// [deleteOnError] whether delete the file when error occurs. /// The default value is [true]. /// + /// [fileMode] + /// {@macro dio.DioFileMode} + /// /// [lengthHeader] : The real size of original file (not compressed). /// When file is compressed: /// 1. If this value is 'content-length', the `total` argument of @@ -242,6 +246,7 @@ abstract class Dio { Map? queryParameters, CancelToken? cancelToken, bool deleteOnError = true, + DioFileMode fileMode = DioFileMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, @@ -254,6 +259,7 @@ abstract class Dio { ProgressCallback? onReceiveProgress, CancelToken? cancelToken, bool deleteOnError = true, + DioFileMode mode = DioFileMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, @@ -266,6 +272,7 @@ abstract class Dio { deleteOnError: deleteOnError, cancelToken: cancelToken, data: data, + fileMode: mode, options: options, ); } diff --git a/dio/lib/src/dio/dio_for_native.dart b/dio/lib/src/dio/dio_for_native.dart index 1e016935d..e169fabb7 100644 --- a/dio/lib/src/dio/dio_for_native.dart +++ b/dio/lib/src/dio/dio_for_native.dart @@ -6,6 +6,7 @@ import '../adapters/io_adapter.dart'; import '../cancel_token.dart'; import '../dio.dart'; import '../dio_exception.dart'; +import '../dio_file_mode.dart'; import '../dio_mixin.dart'; import '../headers.dart'; import '../options.dart'; @@ -32,6 +33,7 @@ class DioForNative with DioMixin implements Dio { Map? queryParameters, CancelToken? cancelToken, bool deleteOnError = true, + DioFileMode fileMode = DioFileMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, @@ -95,7 +97,12 @@ class DioForNative with DioMixin implements Dio { // Shouldn't call file.writeAsBytesSync(list, flush: flush), // because it can write all bytes by once. Consider that the file is // a very big size (up to 1 Gigabytes), it will be expensive in memory. - RandomAccessFile raf = file.openSync(mode: FileMode.write); + RandomAccessFile raf = file.openSync( + mode: fileMode.map( + write: () => FileMode.write, + append: () => FileMode.append, + ), + ); // Create a Completer to notify the success/error state. final completer = Completer(); diff --git a/dio/lib/src/dio_file_mode.dart b/dio/lib/src/dio_file_mode.dart new file mode 100644 index 000000000..076c6e38a --- /dev/null +++ b/dio/lib/src/dio_file_mode.dart @@ -0,0 +1,24 @@ +/// {@template dio.DioFileMode} +/// The file access mode when downloading the file. +/// - [DioFileMode.write]: Mode for opening a file for reading and writing. +/// The file is overwritten if it already exists. The file is created if it +/// does not already exist +/// - [DioFileMode.append]: Mode for opening a file for reading and writing +/// to the end of it. The file is created if it does not already exist. +/// {@endtemplate} +enum DioFileMode { + write, + append; + + T map({ + required T Function() write, + required T Function() append, + }) { + switch (this) { + case DioFileMode.write: + return write(); + case DioFileMode.append: + return append(); + } + } +} diff --git a/dio/lib/src/dio_mixin.dart b/dio/lib/src/dio_mixin.dart index dbc1bd96b..2c8ada648 100644 --- a/dio/lib/src/dio_mixin.dart +++ b/dio/lib/src/dio_mixin.dart @@ -11,6 +11,7 @@ import 'adapter.dart'; import 'cancel_token.dart'; import 'dio.dart'; import 'dio_exception.dart'; +import 'dio_file_mode.dart'; import 'form_data.dart'; import 'headers.dart'; import 'interceptors/imply_content_type.dart'; @@ -286,6 +287,7 @@ abstract class DioMixin implements Dio { ProgressCallback? onReceiveProgress, CancelToken? cancelToken, bool deleteOnError = true, + DioFileMode mode = DioFileMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, @@ -310,6 +312,7 @@ abstract class DioMixin implements Dio { Map? queryParameters, CancelToken? cancelToken, bool deleteOnError = true, + DioFileMode fileMode = DioFileMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, diff --git a/plugins/web_adapter/lib/src/dio_impl.dart b/plugins/web_adapter/lib/src/dio_impl.dart index a9b777f6f..968141a08 100644 --- a/plugins/web_adapter/lib/src/dio_impl.dart +++ b/plugins/web_adapter/lib/src/dio_impl.dart @@ -22,6 +22,7 @@ class DioForBrowser with DioMixin implements Dio { Map? queryParameters, CancelToken? cancelToken, bool deleteOnError = true, + DioFileMode fileMode = DioFileMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, From 3266e0fb023c5b740e8680d0e95496db87f4aac2 Mon Sep 17 00:00:00 2001 From: Shehab Mohamed Date: Sun, 1 Sep 2024 09:53:40 +0300 Subject: [PATCH 02/11] Add append download test with the new [DioFileMode] --- dio_test/lib/src/test/download_tests.dart | 48 +++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/dio_test/lib/src/test/download_tests.dart b/dio_test/lib/src/test/download_tests.dart index f81e30a9c..660e8c9c9 100644 --- a/dio_test/lib/src/test/download_tests.dart +++ b/dio_test/lib/src/test/download_tests.dart @@ -380,6 +380,54 @@ void downloadTests( completes, ); }); + test('append bytes previous download', () async { + final cancelToken = CancelToken(); + final path = p.join(tmp.path, 'download_3.txt'); + final requestedBytes = 1024 * 1024 * 10; + var recievedBytes1 = 0; + await expectLater( + dio.download( + '/bytes/$requestedBytes', + path, + cancelToken: cancelToken, + onReceiveProgress: (c, t) { + if (c > 5000) { + recievedBytes1 = c; + cancelToken.cancel(); + } + }, + deleteOnError: false, + ), + throwsDioException( + DioExceptionType.cancel, + stackTraceContains: 'test/download_tests.dart', + ), + ); + + final cancelToken2 = CancelToken(); + var recievedBytes2 = 0; + expectLater( + dio.download( + '/bytes/$requestedBytes', + path, + cancelToken: cancelToken, + onReceiveProgress: (c, t) { + recievedBytes2 = c; + if (c > 5000) { + cancelToken2.cancel(); + } + }, + deleteOnError: false, + fileMode: DioFileMode.append, + ), + throwsDioException( + DioExceptionType.cancel, + stackTraceContains: 'test/download_tests.dart', + ), + ); + await Future.delayed(const Duration(milliseconds: 100), () {}); + expect(File(path).lengthSync(), recievedBytes1 + recievedBytes2); + }); }, testOn: 'vm', ); From cf5f6bf00bc7beb4b3efeb158fc39f5509d09980 Mon Sep 17 00:00:00 2001 From: Shehab Mohamed Date: Thu, 5 Sep 2024 14:47:44 +0300 Subject: [PATCH 03/11] Apply dart formatting --- dio/lib/dio.dart | 2 +- dio/lib/src/dio.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dio/lib/dio.dart b/dio/lib/dio.dart index db5c49ccb..68d2dfe9d 100644 --- a/dio/lib/dio.dart +++ b/dio/lib/dio.dart @@ -19,4 +19,4 @@ export 'src/options.dart'; export 'src/parameter.dart'; export 'src/redirect_record.dart'; export 'src/response.dart'; -export 'src/transformer.dart'; \ No newline at end of file +export 'src/transformer.dart'; diff --git a/dio/lib/src/dio.dart b/dio/lib/src/dio.dart index 084847b72..92c9b7110 100644 --- a/dio/lib/src/dio.dart +++ b/dio/lib/src/dio.dart @@ -210,9 +210,9 @@ abstract class Dio { /// [deleteOnError] whether delete the file when error occurs. /// The default value is [true]. /// - /// [fileMode] + /// [fileMode] /// {@macro dio.DioFileMode} - /// + /// /// [lengthHeader] : The real size of original file (not compressed). /// When file is compressed: /// 1. If this value is 'content-length', the `total` argument of From 8eee3129aa444ee75f2e1bb2706cb424294c6388 Mon Sep 17 00:00:00 2001 From: Shehab Mohamed Date: Thu, 24 Oct 2024 01:47:21 +0300 Subject: [PATCH 04/11] change dio_file_mode.dart to file_access_mode.dart change [DioFileMode] to [FileAccessMode] change [Dio.download(fileMode:)] to [dio.download(fileAccessMode:)] --- dio/lib/dio.dart | 2 +- dio/lib/src/dio.dart | 12 ++++++------ dio/lib/src/dio/dio_for_native.dart | 6 +++--- dio/lib/src/dio_mixin.dart | 6 +++--- ...{dio_file_mode.dart => file_access_mode.dart} | 16 +++++++++------- dio_test/lib/src/test/download_tests.dart | 4 ++-- plugins/web_adapter/lib/src/dio_impl.dart | 2 +- 7 files changed, 25 insertions(+), 23 deletions(-) rename dio/lib/src/{dio_file_mode.dart => file_access_mode.dart} (55%) diff --git a/dio/lib/dio.dart b/dio/lib/dio.dart index 68d2dfe9d..73a9f4f1c 100644 --- a/dio/lib/dio.dart +++ b/dio/lib/dio.dart @@ -9,7 +9,7 @@ export 'src/adapter.dart'; export 'src/cancel_token.dart'; export 'src/dio.dart'; export 'src/dio_exception.dart'; -export 'src/dio_file_mode.dart'; +export 'src/file_access_mode.dart'; export 'src/dio_mixin.dart' hide InterceptorState, InterceptorResultType; export 'src/form_data.dart'; export 'src/headers.dart'; diff --git a/dio/lib/src/dio.dart b/dio/lib/src/dio.dart index 92c9b7110..0d40280cb 100644 --- a/dio/lib/src/dio.dart +++ b/dio/lib/src/dio.dart @@ -5,7 +5,7 @@ import 'cancel_token.dart'; import 'dio/dio_for_native.dart' if (dart.library.js_interop) 'dio/dio_for_browser.dart' if (dart.library.html) 'dio/dio_for_browser.dart'; -import 'dio_file_mode.dart'; +import 'file_access_mode.dart'; import 'dio_mixin.dart'; import 'headers.dart'; import 'options.dart'; @@ -210,8 +210,8 @@ abstract class Dio { /// [deleteOnError] whether delete the file when error occurs. /// The default value is [true]. /// - /// [fileMode] - /// {@macro dio.DioFileMode} + /// [fileAccessMode] + /// {@macro dio.FileAccessMode} /// /// [lengthHeader] : The real size of original file (not compressed). /// When file is compressed: @@ -246,7 +246,7 @@ abstract class Dio { Map? queryParameters, CancelToken? cancelToken, bool deleteOnError = true, - DioFileMode fileMode = DioFileMode.write, + FileAccessMode fileAccessMode = FileAccessMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, @@ -259,7 +259,7 @@ abstract class Dio { ProgressCallback? onReceiveProgress, CancelToken? cancelToken, bool deleteOnError = true, - DioFileMode mode = DioFileMode.write, + FileAccessMode mode = FileAccessMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, @@ -272,7 +272,7 @@ abstract class Dio { deleteOnError: deleteOnError, cancelToken: cancelToken, data: data, - fileMode: mode, + fileAccessMode: mode, options: options, ); } diff --git a/dio/lib/src/dio/dio_for_native.dart b/dio/lib/src/dio/dio_for_native.dart index e169fabb7..d49f429a4 100644 --- a/dio/lib/src/dio/dio_for_native.dart +++ b/dio/lib/src/dio/dio_for_native.dart @@ -6,7 +6,7 @@ import '../adapters/io_adapter.dart'; import '../cancel_token.dart'; import '../dio.dart'; import '../dio_exception.dart'; -import '../dio_file_mode.dart'; +import '../file_access_mode.dart'; import '../dio_mixin.dart'; import '../headers.dart'; import '../options.dart'; @@ -33,7 +33,7 @@ class DioForNative with DioMixin implements Dio { Map? queryParameters, CancelToken? cancelToken, bool deleteOnError = true, - DioFileMode fileMode = DioFileMode.write, + FileAccessMode fileAccessMode = FileAccessMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, @@ -98,7 +98,7 @@ class DioForNative with DioMixin implements Dio { // because it can write all bytes by once. Consider that the file is // a very big size (up to 1 Gigabytes), it will be expensive in memory. RandomAccessFile raf = file.openSync( - mode: fileMode.map( + mode: fileAccessMode.map( write: () => FileMode.write, append: () => FileMode.append, ), diff --git a/dio/lib/src/dio_mixin.dart b/dio/lib/src/dio_mixin.dart index 2c8ada648..c529ac6d2 100644 --- a/dio/lib/src/dio_mixin.dart +++ b/dio/lib/src/dio_mixin.dart @@ -11,7 +11,7 @@ import 'adapter.dart'; import 'cancel_token.dart'; import 'dio.dart'; import 'dio_exception.dart'; -import 'dio_file_mode.dart'; +import 'file_access_mode.dart'; import 'form_data.dart'; import 'headers.dart'; import 'interceptors/imply_content_type.dart'; @@ -287,7 +287,7 @@ abstract class DioMixin implements Dio { ProgressCallback? onReceiveProgress, CancelToken? cancelToken, bool deleteOnError = true, - DioFileMode mode = DioFileMode.write, + FileAccessMode mode = FileAccessMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, @@ -312,7 +312,7 @@ abstract class DioMixin implements Dio { Map? queryParameters, CancelToken? cancelToken, bool deleteOnError = true, - DioFileMode fileMode = DioFileMode.write, + FileAccessMode fileAccessMode = FileAccessMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, diff --git a/dio/lib/src/dio_file_mode.dart b/dio/lib/src/file_access_mode.dart similarity index 55% rename from dio/lib/src/dio_file_mode.dart rename to dio/lib/src/file_access_mode.dart index 076c6e38a..9d5dd25ec 100644 --- a/dio/lib/src/dio_file_mode.dart +++ b/dio/lib/src/file_access_mode.dart @@ -1,23 +1,25 @@ -/// {@template dio.DioFileMode} +/// {@template dio.FileAccessMode} /// The file access mode when downloading the file. -/// - [DioFileMode.write]: Mode for opening a file for reading and writing. +/// - [FileAccessMode.write]: Mode for opening a file for reading and writing. /// The file is overwritten if it already exists. The file is created if it /// does not already exist -/// - [DioFileMode.append]: Mode for opening a file for reading and writing +/// - [FileAccessMode.append]: Mode for opening a file for reading and writing /// to the end of it. The file is created if it does not already exist. /// {@endtemplate} -enum DioFileMode { +enum FileAccessMode { write, - append; + append, +} +extension FileAccessModeExtension on FileAccessMode { T map({ required T Function() write, required T Function() append, }) { switch (this) { - case DioFileMode.write: + case FileAccessMode.write: return write(); - case DioFileMode.append: + case FileAccessMode.append: return append(); } } diff --git a/dio_test/lib/src/test/download_tests.dart b/dio_test/lib/src/test/download_tests.dart index 660e8c9c9..98fa168b1 100644 --- a/dio_test/lib/src/test/download_tests.dart +++ b/dio_test/lib/src/test/download_tests.dart @@ -380,7 +380,7 @@ void downloadTests( completes, ); }); - test('append bytes previous download', () async { + test('append bytes to previous download', () async { final cancelToken = CancelToken(); final path = p.join(tmp.path, 'download_3.txt'); final requestedBytes = 1024 * 1024 * 10; @@ -418,7 +418,7 @@ void downloadTests( } }, deleteOnError: false, - fileMode: DioFileMode.append, + fileAccessMode: FileAccessMode.append, ), throwsDioException( DioExceptionType.cancel, diff --git a/plugins/web_adapter/lib/src/dio_impl.dart b/plugins/web_adapter/lib/src/dio_impl.dart index 968141a08..4b797e625 100644 --- a/plugins/web_adapter/lib/src/dio_impl.dart +++ b/plugins/web_adapter/lib/src/dio_impl.dart @@ -22,7 +22,7 @@ class DioForBrowser with DioMixin implements Dio { Map? queryParameters, CancelToken? cancelToken, bool deleteOnError = true, - DioFileMode fileMode = DioFileMode.write, + FileAccessMode fileAccessMode = FileAccessMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, From 27bb332c8ca2c2b9062fcd76c793e214d4377b5e Mon Sep 17 00:00:00 2001 From: shehab mohame Date: Mon, 16 Dec 2024 17:58:52 +0200 Subject: [PATCH 05/11] Apply suggestions from code review Co-authored-by: Alex Li Signed-off-by: shehab mohame --- dio/lib/src/file_access_mode.dart | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/dio/lib/src/file_access_mode.dart b/dio/lib/src/file_access_mode.dart index 9d5dd25ec..ad74ddb4e 100644 --- a/dio/lib/src/file_access_mode.dart +++ b/dio/lib/src/file_access_mode.dart @@ -1,13 +1,14 @@ -/// {@template dio.FileAccessMode} -/// The file access mode when downloading the file. -/// - [FileAccessMode.write]: Mode for opening a file for reading and writing. -/// The file is overwritten if it already exists. The file is created if it -/// does not already exist -/// - [FileAccessMode.append]: Mode for opening a file for reading and writing -/// to the end of it. The file is created if it does not already exist. +/// {@template dio.options.FileAccessMode} +/// The file access mode when downloading a file, corresponds to a subset of +/// dart:io::[FileMode]. /// {@endtemplate} enum FileAccessMode { + /// Mode for opening a file for reading and writing. The file is overwritten + /// if it already exists. The file is created if it does not already exist. write, + + /// Mode for opening a file for reading and writing to the end of it. + /// The file is created if it does not already exist. append, } From 42767429710cde298a187b23a543ce3b091f0986 Mon Sep 17 00:00:00 2001 From: Shehab Mohamed Date: Mon, 16 Dec 2024 18:10:31 +0200 Subject: [PATCH 06/11] Moving FileAccessMode from "file_access_mode.dart" to "options.dart" Remove [FileAccessModeExtension] --- dio/lib/dio.dart | 1 - dio/lib/src/dio.dart | 1 - dio/lib/src/dio/dio_for_native.dart | 8 +++----- dio/lib/src/dio_mixin.dart | 1 - dio/lib/src/file_access_mode.dart | 27 --------------------------- dio/lib/src/options.dart | 14 ++++++++++++++ 6 files changed, 17 insertions(+), 35 deletions(-) delete mode 100644 dio/lib/src/file_access_mode.dart diff --git a/dio/lib/dio.dart b/dio/lib/dio.dart index 73a9f4f1c..eda699923 100644 --- a/dio/lib/dio.dart +++ b/dio/lib/dio.dart @@ -9,7 +9,6 @@ export 'src/adapter.dart'; export 'src/cancel_token.dart'; export 'src/dio.dart'; export 'src/dio_exception.dart'; -export 'src/file_access_mode.dart'; export 'src/dio_mixin.dart' hide InterceptorState, InterceptorResultType; export 'src/form_data.dart'; export 'src/headers.dart'; diff --git a/dio/lib/src/dio.dart b/dio/lib/src/dio.dart index 0d40280cb..23e580f46 100644 --- a/dio/lib/src/dio.dart +++ b/dio/lib/src/dio.dart @@ -5,7 +5,6 @@ import 'cancel_token.dart'; import 'dio/dio_for_native.dart' if (dart.library.js_interop) 'dio/dio_for_browser.dart' if (dart.library.html) 'dio/dio_for_browser.dart'; -import 'file_access_mode.dart'; import 'dio_mixin.dart'; import 'headers.dart'; import 'options.dart'; diff --git a/dio/lib/src/dio/dio_for_native.dart b/dio/lib/src/dio/dio_for_native.dart index d49f429a4..6e8f2b95a 100644 --- a/dio/lib/src/dio/dio_for_native.dart +++ b/dio/lib/src/dio/dio_for_native.dart @@ -6,7 +6,6 @@ import '../adapters/io_adapter.dart'; import '../cancel_token.dart'; import '../dio.dart'; import '../dio_exception.dart'; -import '../file_access_mode.dart'; import '../dio_mixin.dart'; import '../headers.dart'; import '../options.dart'; @@ -98,10 +97,9 @@ class DioForNative with DioMixin implements Dio { // because it can write all bytes by once. Consider that the file is // a very big size (up to 1 Gigabytes), it will be expensive in memory. RandomAccessFile raf = file.openSync( - mode: fileAccessMode.map( - write: () => FileMode.write, - append: () => FileMode.append, - ), + mode: fileAccessMode == FileAccessMode.write + ? FileMode.write + : FileMode.append, ); // Create a Completer to notify the success/error state. diff --git a/dio/lib/src/dio_mixin.dart b/dio/lib/src/dio_mixin.dart index c529ac6d2..4bec4f1e0 100644 --- a/dio/lib/src/dio_mixin.dart +++ b/dio/lib/src/dio_mixin.dart @@ -11,7 +11,6 @@ import 'adapter.dart'; import 'cancel_token.dart'; import 'dio.dart'; import 'dio_exception.dart'; -import 'file_access_mode.dart'; import 'form_data.dart'; import 'headers.dart'; import 'interceptors/imply_content_type.dart'; diff --git a/dio/lib/src/file_access_mode.dart b/dio/lib/src/file_access_mode.dart deleted file mode 100644 index ad74ddb4e..000000000 --- a/dio/lib/src/file_access_mode.dart +++ /dev/null @@ -1,27 +0,0 @@ -/// {@template dio.options.FileAccessMode} -/// The file access mode when downloading a file, corresponds to a subset of -/// dart:io::[FileMode]. -/// {@endtemplate} -enum FileAccessMode { - /// Mode for opening a file for reading and writing. The file is overwritten - /// if it already exists. The file is created if it does not already exist. - write, - - /// Mode for opening a file for reading and writing to the end of it. - /// The file is created if it does not already exist. - append, -} - -extension FileAccessModeExtension on FileAccessMode { - T map({ - required T Function() write, - required T Function() append, - }) { - switch (this) { - case FileAccessMode.write: - return write(); - case FileAccessMode.append: - return append(); - } - } -} diff --git a/dio/lib/src/options.dart b/dio/lib/src/options.dart index 1f1e58983..1e3842fc0 100644 --- a/dio/lib/src/options.dart +++ b/dio/lib/src/options.dart @@ -753,3 +753,17 @@ class _RequestConfig { ResponseDecoder? responseDecoder; late ListFormat listFormat; } + +/// {@template dio.options.FileAccessMode} +/// The file access mode when downloading a file, corresponds to a subset of +/// dart:io::[FileMode]. +/// {@endtemplate} +enum FileAccessMode { + /// Mode for opening a file for reading and writing. The file is overwritten + /// if it already exists. The file is created if it does not already exist. + write, + + /// Mode for opening a file for reading and writing to the end of it. + /// The file is created if it does not already exist. + append, +} From 6c45ae5887abd61798d5053ea1c35fece1328896 Mon Sep 17 00:00:00 2001 From: shehab mohame Date: Tue, 17 Dec 2024 11:40:05 +0200 Subject: [PATCH 07/11] Fix [FileAccessMode] comments in dio/lib/src/dio.dart Co-authored-by: Alex Li Signed-off-by: shehab mohame --- dio/lib/src/dio.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dio/lib/src/dio.dart b/dio/lib/src/dio.dart index 23e580f46..727a9d5dc 100644 --- a/dio/lib/src/dio.dart +++ b/dio/lib/src/dio.dart @@ -210,7 +210,7 @@ abstract class Dio { /// The default value is [true]. /// /// [fileAccessMode] - /// {@macro dio.FileAccessMode} + /// {@macro dio.options.FileAccessMode} /// /// [lengthHeader] : The real size of original file (not compressed). /// When file is compressed: From c2a23e8735a53e7a8b03aae84f3a1dfcabdd8b37 Mon Sep 17 00:00:00 2001 From: shehab mohame Date: Tue, 17 Dec 2024 11:40:38 +0200 Subject: [PATCH 08/11] format dio_test/lib/src/test/download_tests.dart Co-authored-by: Alex Li Signed-off-by: shehab mohame --- dio_test/lib/src/test/download_tests.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/dio_test/lib/src/test/download_tests.dart b/dio_test/lib/src/test/download_tests.dart index 98fa168b1..6041f241b 100644 --- a/dio_test/lib/src/test/download_tests.dart +++ b/dio_test/lib/src/test/download_tests.dart @@ -380,6 +380,7 @@ void downloadTests( completes, ); }); + test('append bytes to previous download', () async { final cancelToken = CancelToken(); final path = p.join(tmp.path, 'download_3.txt'); From ef26620c9c082fc6f95f575b8d9843cea2f397d2 Mon Sep 17 00:00:00 2001 From: Shehab Mohamed Date: Thu, 26 Dec 2024 08:36:47 +0200 Subject: [PATCH 09/11] Rename "mode" in `Dio.downloadUri` to "fileAccessMode" Rename "mode" in `DioMixin.downloadUri` to "fileAccessMode" Change var to int in "appeand bytes to previos download" test --- dio/lib/src/dio.dart | 4 ++-- dio/lib/src/dio_mixin.dart | 3 ++- dio_test/lib/src/test/download_tests.dart | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/dio/lib/src/dio.dart b/dio/lib/src/dio.dart index 727a9d5dc..a29b6e189 100644 --- a/dio/lib/src/dio.dart +++ b/dio/lib/src/dio.dart @@ -258,7 +258,7 @@ abstract class Dio { ProgressCallback? onReceiveProgress, CancelToken? cancelToken, bool deleteOnError = true, - FileAccessMode mode = FileAccessMode.write, + FileAccessMode fileAccessMode = FileAccessMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, @@ -271,7 +271,7 @@ abstract class Dio { deleteOnError: deleteOnError, cancelToken: cancelToken, data: data, - fileAccessMode: mode, + fileAccessMode: fileAccessMode, options: options, ); } diff --git a/dio/lib/src/dio_mixin.dart b/dio/lib/src/dio_mixin.dart index 4bec4f1e0..f320e68c3 100644 --- a/dio/lib/src/dio_mixin.dart +++ b/dio/lib/src/dio_mixin.dart @@ -286,7 +286,7 @@ abstract class DioMixin implements Dio { ProgressCallback? onReceiveProgress, CancelToken? cancelToken, bool deleteOnError = true, - FileAccessMode mode = FileAccessMode.write, + FileAccessMode fileAccessMode = FileAccessMode.write, String lengthHeader = Headers.contentLengthHeader, Object? data, Options? options, @@ -299,6 +299,7 @@ abstract class DioMixin implements Dio { deleteOnError: deleteOnError, cancelToken: cancelToken, data: data, + fileAccessMode: fileAccessMode, options: options, ); } diff --git a/dio_test/lib/src/test/download_tests.dart b/dio_test/lib/src/test/download_tests.dart index 6041f241b..7fc43141d 100644 --- a/dio_test/lib/src/test/download_tests.dart +++ b/dio_test/lib/src/test/download_tests.dart @@ -385,7 +385,7 @@ void downloadTests( final cancelToken = CancelToken(); final path = p.join(tmp.path, 'download_3.txt'); final requestedBytes = 1024 * 1024 * 10; - var recievedBytes1 = 0; + int recievedBytes1 = 0; await expectLater( dio.download( '/bytes/$requestedBytes', @@ -406,7 +406,7 @@ void downloadTests( ); final cancelToken2 = CancelToken(); - var recievedBytes2 = 0; + int recievedBytes2 = 0; expectLater( dio.download( '/bytes/$requestedBytes', From ff334f77fa846a3fd7e0056999b5901d46281300 Mon Sep 17 00:00:00 2001 From: Shehab Mohamed Date: Thu, 26 Dec 2024 08:37:28 +0200 Subject: [PATCH 10/11] Update dio CHANGELOG --- dio/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/dio/CHANGELOG.md b/dio/CHANGELOG.md index 4243c1626..491ea0680 100644 --- a/dio/CHANGELOG.md +++ b/dio/CHANGELOG.md @@ -8,6 +8,7 @@ See the [Migration Guide][] for the complete breaking changes list.** - Update comments and strings with `MultipartFile`. - Removes redundant warnings when composing request options on Web. - Fixes boundary inconsistency in `FormData.clone()`. +- Support `FileAccessMode` in `Dio.download` and `Dio.downloadUri` to change download file opening mode ## 5.7.0 From f54c19cf93f8296c2256400fa3ab4b40d355d38e Mon Sep 17 00:00:00 2001 From: Shehab Mohamed Date: Thu, 26 Dec 2024 08:37:59 +0200 Subject: [PATCH 11/11] Update web_adapter CHANGELOG --- plugins/web_adapter/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/web_adapter/CHANGELOG.md b/plugins/web_adapter/CHANGELOG.md index 85b25e88d..61bfc7717 100644 --- a/plugins/web_adapter/CHANGELOG.md +++ b/plugins/web_adapter/CHANGELOG.md @@ -1,6 +1,6 @@ ## Unreleased -*None.* +- Support `FileAccessMode` in `Dio.download` and `Dio.downloadUri` to change download file opening mode ## 2.0.0