-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Bad state: Can't finalize a finalized MultipartFile #482
Comments
Because |
I tried this way, but the original // The rest is the same of interceptor_lock example
}).then((e) {
//repeat
if (options.data is FormData) {
FormData formData = FormData();
formData.fields.addAll(options.data.fields);
for (MapEntry mapFile in options.data.files) {
formData.files.add(MapEntry(
mapFile.key,
MultipartFile.fromFileSync(???mapFile.value.FILE_PATH???,
filename: mapFile.value.filename)));
}
options.data = formData;
}
return dio.request(options.path, options: options);
} |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If this is still an issue, please make sure it is up to date and if so, add a comment that this is still an issue to keep it open. Thank you for your contributions. |
I have the same issue, any tips? |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If this is still an issue, please make sure it is up to date and if so, add a comment that this is still an issue to keep it open. Thank you for your contributions. |
thx!saved my day! |
how to get the multipartFile file path ??? |
Why is this issue closed? it's still relevant today. Possible solutions
WorkaroundIf anyone is looking for a workaround, one can:
|
@matanshukry you can easily add field |
@liweiwh Sending extra data over the network when it's not needed (it's used locally only) is a bad option |
@matanshukry you can delete it when you do the request.
|
If you delete it from the request, how will it exist in the interceptor? |
@matanshukry oh, sorry, my mistake, I use it in my refresh token process, but when the first time do the request the |
If you are resending the same formData in a nested dio request eg
be sure to re-initiate form data because it is already finalized |
I made my own custom multipart class that can store file path, the solution as @matanshukry pointed out, if anyone is interested: import 'dart:async';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:http_parser/http_parser.dart';
import 'package:path/path.dart' as p;
class MultipartFileExtended extends MultipartFile {
final String filePath; //this one!
MultipartFileExtended(
Stream<List<int>> stream,
length, {
filename,
this.filePath,
contentType,
}) : super(stream, length, filename: filename, contentType: contentType);
static MultipartFileExtended fromFileSync(
String filePath, {
String filename,
MediaType contentType,
}) => multipartFileFromPathSync(filePath, filename: filename, contentType: contentType);
}
MultipartFileExtended multipartFileFromPathSync(
String filePath, {
String filename,
MediaType contentType,
}) {
filename ??= p.basename(filePath);
var file = File(filePath);
var length = file.lengthSync();
var stream = file.openRead();
return MultipartFileExtended(
stream,
length,
filename: filename,
contentType: contentType,
filePath: filePath,
);
} Now you can call request like this: Dio dio = new Dio();
FormData formData = FormData.fromMap({
"file": MultipartFileExtended.fromFileSync("./example/upload.txt",
filename: "upload.txt")
});
var response = await dio.post("/info", data: formData).then((e) {
FormData newFormData = FormData();
newFormData.fields.addAll(formData.fields);
for (MapEntry mapFile in formData.files) {
newFormData.files.add(MapEntry(
mapFile.key,
MultipartFileExtended.fromFileSync(mapFile.value.filePath, //fixed!
filename: mapFile.value.filename)));
}
return dio.post("/info", data: newFormData);
}); |
thanks @indokan2001 , your solution works for my case. }).then((e) {
// repeat
if (options.data is FormData) {
// https://github.com/flutterchina/dio/issues/482
FormData formData = FormData();
formData.fields.addAll(options.data.fields);
for (MapEntry mapFile in options.data.files) {
formData.files.add(MapEntry(
mapFile.key,
MultipartFileExtended.fromFileSync(mapFile.value.filePath,
filename: mapFile.value.filename)));
}
options.data = formData;
}
return dio.request(options.path, options: options);
}); |
the problem still exists |
just create a function which returns dio request and use it again when you came across this error |
just replace file path "/" with a "@" and make it as a filename in multipartfile and after refresh token resending request use this filename and restore it by replacing "@" with "/" now path is ready create a new multipartfile with that path. solved!!. |
You can just reset the list in which you are storing the multipartfile after the request is made. |
How about MultipartFile that are from bytes? |
Anyone using dio_smart_retry and have the same issue? I'm using it with dio , and when get second or third retry, causes this error.... |
I am using dio_smart_retry and got this error. But on the initial request, and the subsequent. |
i got same one |
@aweiand @fasterlars please test my fix rodion-m/dio_smart_retry@ac4c291 |
@vimaxwell I have not seen this error in a while, but will try your fix if I see it again and are able to reproduce it. |
Hi @vimaxwell , After test in a test server I own, the issue persists... |
Starting from version 1.4.0 dio_smart_retry package supports retrying for requests with multipart/form-data. |
Hi @rodion-m, how to |
|
…1714) Help issues like #482 to understand what happened exactly. ### New Pull Request Checklist - [x] I have read the [Documentation](https://pub.dev/documentation/dio/latest/) - [x] I have searched for a similar pull request in the [project](https://github.com/cfug/dio/pulls) and found none - [x] I have updated this branch with the latest `main` branch to avoid conflicts (via merge from master or rebase) - [ ] I have added the required tests to prove the fix/feature I'm adding - [x] I have updated the documentation (if necessary) - [x] I have run the tests without failures - [ ] I have updated the `CHANGELOG.md` in the corresponding package ### Additional context and info (if any) As an improvement with comments and docs, it doesn't require a version change. --------- Signed-off-by: Alex Li <[email protected]> Co-authored-by: Peter Leibiger <[email protected]>
Awesome. It worked ...
if (options.data is FormData) {
FormData formData = FormData();
formData.fields.addAll(options.data.fields);
for (MapEntry mapFile in options.data.files) {
formData.files.add(MapEntry(
mapFile.key,
await MultipartFile.fromFile(
(mapFile.value as MultipartFile).filename ?? "",
filename: "${(mapFile.value as MultipartFile).filename}"),
));
}
options.data = formData;
final Response response = await dio.fetch(options);
return handler.resolve(response);
} |
…a 401 Penyebabnya adalah karena Bad state: Can't finalize a finalized MultipartFile. Arti dari pesan ini ialah si Dio tidak bisa menggunakan form data yang sama untuk request yang berulang-ulang. Jadi, solusinya adalah buat ulang form data-nya menggunakan solusi dari ini cfug/dio#482 (comment).
Hi there! This PR should solve this problem without extra workarounds. Hope you enjoy it <3 |
Take a long time to find, this work for me. The type of mapFile.value is MultipartFile which can use clone() method from MultipartFile Class Library
|
this worked perfectly |
dio/dio/lib/src/multipart_file.dart Lines 169 to 179 in ff4eb26
dio/dio/lib/src/form_data.dart Lines 210 to 218 in ff4eb26
|
New Issue Checklist
Issue Info
Flutter
[√] Flutter (Channel stable, v1.9.1+hotfix.2, on Microsoft Windows [versão 10.0.17763.737], locale pt-BR)
[√] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[√] Android Studio (version 3.5)
[√] Connected device (1 available)
Issue Description and Steps
The update token example is not working if repeat is performed with a Post / FormData.
1- Use an interceptor to update token, as in the interceptor_lock example;
2- Run a POST/FormData;
3- After updating the token, the request is resubmitted;
The text was updated successfully, but these errors were encountered: