Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uploading with FormData throws a TypeError: type 'List<int>' is not a subtype of type 'Uint8List' of 'value' #2236

Closed
fromlabs opened this issue Jun 7, 2024 · 6 comments · Fixed by #2237
Assignees
Labels
b: regression Worked before but not now p: dio Targeting `dio` package s: bug Something isn't working

Comments

@fromlabs
Copy link

fromlabs commented Jun 7, 2024

Package

dio

Version

5.4.3+1

Operating-System

Android, iOS

Adapter

Default Dio

Output of flutter doctor -v

[✓] Flutter (Channel stable, 3.22.1, on macOS 14.5 23F79 darwin-arm64, locale it-IT)
    • Flutter version 3.22.1 on channel stable at /Users/hans/fvm/versions/3.22.1
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision a14f74ff3a (2 weeks ago), 2024-05-22 11:08:21 -0500
    • Engine revision 55eae6864b
    • Dart version 3.4.1
    • DevTools version 2.34.3

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at /Users/hans/Library/Android/sdk
    • Platform android-34, build-tools 34.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 15.4)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 15F31d
    • CocoaPods version 1.15.2

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2023.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)

[✓] IntelliJ IDEA Community Edition (version 2024.1.2)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 80.0.2
    • Dart plugin version 241.17502

[✓] VS Code (version 1.90.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension can be installed from:
      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (5 available)
    • iPhone di Roberto Tassi (mobile) • 00008101-00111C3A0190001E            • ios            • iOS 17.5.1 21F90
    • iPhone 15 Pro Max (mobile)       • 27013218-0307-4598-9E9D-1ADA200AC39C • ios            • com.apple.CoreSimulator.SimRuntime.iOS-17-5 (simulator)
    • macOS (desktop)                  • macos                                • darwin-arm64   • macOS 14.5 23F79 darwin-arm64
    • Mac Designed for iPad (desktop)  • mac-designed-for-ipad                • darwin         • macOS 14.5 23F79 darwin-arm64
    • Chrome (web)                     • chrome                               • web-javascript • Google Chrome 125.0.6422.142

[✓] Network resources
    • All expected network resources are available.

• No issues found!

Dart Version

No response

Steps to Reproduce

final formData = dio.FormData();
// fileData is not a Uint8List!
List<int> fileData = ...;
formData.files.add(MapEntry(
  'file',
  dio.MultipartFile.fromBytes(
    fileData,
    filename: fileName,
    contentType: contentType,
  ),
));

Expected Result

No error

Actual Result

flutter: Uncaught Error: type 'List<int>' is not a subtype of type 'Uint8List' of 'value'
flutter: Stacktrace: #0      _StreamController.add (dart:async/stream_controller.dart:604:14)
flutter: #1      _rootRunUnary (dart:async/zone.dart:1407:47)
flutter: #2      _CustomZone.runUnary (dart:async/zone.dart:1308:19)
flutter: #3      _CustomZone.runUnaryGuarded (dart:async/zone.dart:1217:7)
flutter: #4      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:365:11)
flutter: #5      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:297:7)
flutter: #6      _MultiStreamController.addSync (dart:async/stream_impl.dart:1127:36)
flutter: #7      new Stream.fromIterable.<anonymous closure>.next (dart:async/stream.dart:375:26)
flutter: #8      _rootRun (dart:async/zone.dart:1399:13)
flutter: #9      _CustomZone.run (dart:async/zone.dart:1301:19)
flutter: #10     _CustomZone.runGuarded (dart:async/zone.dart:1209:7)
flutter: #11     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1249:23)
flutter: #12     _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
flutter: #13     _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
@fromlabs fromlabs added h: need triage This issue needs to be categorized s: bug Something isn't working labels Jun 7, 2024
@fromlabs
Copy link
Author

fromlabs commented Jun 7, 2024

I think is related to:

I suppose the problem is in form_data.dart:

final controller = StreamController<Uint8List>(sync: false);

...

Future<void>(() async {
  for (final file in files) {
    writeUtf8('--$boundary$_rn');
    writeUtf8(_headerForFile(file));
    await writeStreamToSink(file.value.finalize(), controller);
    writeLine();
  }
}).then((_) {
  writeUtf8('--$boundary--$_rn');
}).whenComplete(() {
  controller.close();
});

multipart_file.dart
Stream<List<int>> finalize();

Calling writeStreamToSink(Stream<List<int>>, StreamController<Uint8List>) throws a TypeError because is trying to add List<int> to a Uint8List sink.

@AlexV525
Copy link
Member

AlexV525 commented Jun 7, 2024

@fromlabs Could you try updating the implementation to below solve the problem?

Future<void>(() async {
  for (final file in files) {
    writeUtf8('--$boundary$_rn');
    writeUtf8(_headerForFile(file));
    await writeStreamToSink<Uint8List>(
      file.value
          .finalize()
          .map((e) => e is Uint8List ? e : Uint8List.fromList(e)),
      controller,
    );
    writeLine();
  }
}).then((_) {
  writeUtf8('--$boundary--$_rn');
}).whenComplete(() {
  controller.close();
});

@AlexV525 AlexV525 added the h: need more info Further information is requested label Jun 7, 2024
@fromlabs
Copy link
Author

fromlabs commented Jun 7, 2024

Yes I've already tried your solution and it works.

Meanwhile I found a workaround on my code:

dio.MultipartFile.fromBytes(
  Uint8List.fromList(fileData),
  filename: fileName,
  contentType: contentType,
),

Thanks @AlexV525!

@AlexV525
Copy link
Member

AlexV525 commented Jun 7, 2024

@fromlabs Are you able to extract a minimal reproducible example? I'm wondering why the issue (if it exists) escapes from our tests.

@fromlabs
Copy link
Author

fromlabs commented Jun 7, 2024

I think because formdata_test.dart doesn't test directly MultipartFile.fromBytes with real List<int>, but tests just MultipartFile.fromString, MultipartFile.fromFile and MultipartFile.fromFileSync which work under the hood with Uint8List.

@AlexV525
Copy link
Member

AlexV525 commented Jun 7, 2024

Huge thanks for your inputs!

@AlexV525 AlexV525 added p: dio Targeting `dio` package b: regression Worked before but not now and removed h: need more info Further information is requested h: need triage This issue needs to be categorized labels Jun 7, 2024
@AlexV525 AlexV525 self-assigned this Jun 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
b: regression Worked before but not now p: dio Targeting `dio` package s: bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants