From 457c826eb31cd285d90cf029b1f7805c1f01be6e Mon Sep 17 00:00:00 2001 From: lym Date: Thu, 3 Oct 2024 11:50:16 +0800 Subject: [PATCH 1/2] Fix boundary inconsistency in FormData.clone method --- dio/lib/src/form_data.dart | 35 ++++++++++++++++++++++------------- dio/test/formdata_test.dart | 5 +++-- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/dio/lib/src/form_data.dart b/dio/lib/src/form_data.dart index 10bc5f626..df9c80b13 100644 --- a/dio/lib/src/form_data.dart +++ b/dio/lib/src/form_data.dart @@ -19,21 +19,25 @@ String get _nextRandomId => /// A class to create readable "multipart/form-data" streams. /// It can be used to submit forms and file uploads to http server. +/// +/// Note: When initBoundary is specified, it will override the boundaryName configuration. +/// This is because the actual boundary is composed of boundaryName plus a random string. class FormData { FormData({ + String? initBoundary, this.boundaryName = _boundaryName, this.camelCaseContentDisposition = false, }) { - _init(); + _init(initBoundary: initBoundary); } /// Create [FormData] from a [Map]. FormData.fromMap( - Map map, [ - ListFormat listFormat = ListFormat.multi, - this.camelCaseContentDisposition = false, - this.boundaryName = _boundaryName, - ]) { + Map map, [ + ListFormat listFormat = ListFormat.multi, + this.camelCaseContentDisposition = false, + this.boundaryName = _boundaryName, + ]) { _init(fromMap: map, listFormat: listFormat); } @@ -45,17 +49,22 @@ class FormData { final bool camelCaseContentDisposition; void _init({ + String? initBoundary, Map? fromMap, ListFormat listFormat = ListFormat.multi, }) { - // Get an unique boundary for the instance. - _boundary = '$boundaryName-$_nextRandomId'; + if(initBoundary != null) { + _boundary = initBoundary; + }else{ + // Get an unique boundary for the instance. + _boundary = '$boundaryName-$_nextRandomId'; + } if (fromMap != null) { // Use [encodeMap] to recursively add fields and files. // TODO(Alex): Write a proper/elegant implementation. encodeMap( fromMap, - (key, value) { + (key, value) { if (value is MultipartFile) { files.add(MapEntry(key, value)); } else { @@ -165,8 +174,8 @@ class FormData { if (isFinalized) { throw StateError( 'The FormData has already been finalized. ' - 'This typically means you are using ' - 'the same FormData in repeated requests.', + 'This typically means you are using ' + 'the same FormData in repeated requests.', ); } _isFinalized = true; @@ -203,13 +212,13 @@ class FormData { /// Transform the entire FormData contents as a list of bytes asynchronously. Future readAsBytes() { return Future.sync( - () => finalize().reduce((a, b) => Uint8List.fromList([...a, ...b])), + () => finalize().reduce((a, b) => Uint8List.fromList([...a, ...b])), ); } // Convenience method to clone finalized FormData when retrying requests. FormData clone() { - final clone = FormData(); + final clone = FormData(initBoundary: _boundary); clone.fields.addAll(fields); for (final file in files) { clone.files.add(MapEntry(file.key, file.value.clone())); diff --git a/dio/test/formdata_test.dart b/dio/test/formdata_test.dart index 109a53246..e547b16c1 100644 --- a/dio/test/formdata_test.dart +++ b/dio/test/formdata_test.dart @@ -10,7 +10,7 @@ void main() async { group(FormData, () { test( 'complex', - () async { + () async { final fm = FormData.fromMap({ 'name': 'wendux', 'age': 25, @@ -119,7 +119,7 @@ void main() async { test( 'complex cloning FormData object', - () async { + () async { final fm = FormData.fromMap({ 'name': 'wendux', 'age': 25, @@ -176,6 +176,7 @@ void main() async { expect(fm1 != fm, true); expect(fm1.files[0].value.filename, fm.files[0].value.filename); expect(fm1.fields, fm.fields); + expect(fm1.boundary, fm.boundary); }, testOn: 'vm', ); From 2da1e86c6ea935ffcbf01343aba92ae04bc906e2 Mon Sep 17 00:00:00 2001 From: lym Date: Thu, 3 Oct 2024 11:57:06 +0800 Subject: [PATCH 2/2] Fix boundary inconsistency in FormData.clone method --- dio/lib/src/form_data.dart | 18 +++++++++--------- dio/test/formdata_test.dart | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/dio/lib/src/form_data.dart b/dio/lib/src/form_data.dart index df9c80b13..4c3cf4753 100644 --- a/dio/lib/src/form_data.dart +++ b/dio/lib/src/form_data.dart @@ -33,11 +33,11 @@ class FormData { /// Create [FormData] from a [Map]. FormData.fromMap( - Map map, [ - ListFormat listFormat = ListFormat.multi, - this.camelCaseContentDisposition = false, - this.boundaryName = _boundaryName, - ]) { + Map map, [ + ListFormat listFormat = ListFormat.multi, + this.camelCaseContentDisposition = false, + this.boundaryName = _boundaryName, + ]) { _init(fromMap: map, listFormat: listFormat); } @@ -64,7 +64,7 @@ class FormData { // TODO(Alex): Write a proper/elegant implementation. encodeMap( fromMap, - (key, value) { + (key, value) { if (value is MultipartFile) { files.add(MapEntry(key, value)); } else { @@ -174,8 +174,8 @@ class FormData { if (isFinalized) { throw StateError( 'The FormData has already been finalized. ' - 'This typically means you are using ' - 'the same FormData in repeated requests.', + 'This typically means you are using ' + 'the same FormData in repeated requests.', ); } _isFinalized = true; @@ -212,7 +212,7 @@ class FormData { /// Transform the entire FormData contents as a list of bytes asynchronously. Future readAsBytes() { return Future.sync( - () => finalize().reduce((a, b) => Uint8List.fromList([...a, ...b])), + () => finalize().reduce((a, b) => Uint8List.fromList([...a, ...b])), ); } diff --git a/dio/test/formdata_test.dart b/dio/test/formdata_test.dart index e547b16c1..ee299ecdf 100644 --- a/dio/test/formdata_test.dart +++ b/dio/test/formdata_test.dart @@ -10,7 +10,7 @@ void main() async { group(FormData, () { test( 'complex', - () async { + () async { final fm = FormData.fromMap({ 'name': 'wendux', 'age': 25, @@ -119,7 +119,7 @@ void main() async { test( 'complex cloning FormData object', - () async { + () async { final fm = FormData.fromMap({ 'name': 'wendux', 'age': 25,