Hello
As suggested here, I would like to submit one issue with http.MultipartRequest. How to support utf-8 format for the body fields?
I'm writing a Flutter application, which includes a form to upload one image along with form fields
Future<Map<String, dynamic>> multipartPostRequest(String method, String route, Map<String, String> bodyFields, List<http.MultipartFile> files) async {
// method = POST or PUT...
var url = Uri.parse( Application.backendBaseURL + route);
var request = new http.MultipartRequest(method, url)
..fields.addAll(bodyFields);
if (files != null && files.length > 0)
request.files.addAll(files);
return LocalAuth.getJWToken()
.then((token) {
request.headers[HttpHeaders.AUTHORIZATION] = 'Bearer $token';
return request.send();
})
.then((streamedResponse) {
_updateJWTokenFrom(streamedResponse);
return http.Response.fromStream(streamedResponse);
})
.then((response) {
return response.body;
})
.then((body) {
if (isJSON(body))
return json.decode(body);
else
return {'mssg': body};
})
.catchError((e) {
return {'mssg': 'Got error: $e'};
});
}
}
This code for making a POST as multipart/form-data works well, but whan a body field contains characters such as é à ç, the field is reset to empty. So my question is how can I make a post multipart/form-data with fields in utf-8 ?
Trying to add request.headers[HttpHeaders.CONTENT_TYPE] = 'multipart/form-data;charset=utf-8';does not change.
Thanks a lot in advance
I'm not sure I understand exactly what's going on. You say "when a body field contains characters such as é à ç, the field is reset to empty"... what does it mean for the field to be "reset to empty"? Is the field empty in the in-flight request data? Or are you checking based on how the server treats the data? Are you sure it's not an issue with the server's handling of UTF-8?
Thanks. My form in my mobile application mainly contains two text inputs (title and content) and one file input (for image).
The API server is developed in Go, and I test the condition if the body parameters corresponding to the text inputs are not empty. My server implementation works. I tested with Postman with the characters ç à é etc
Here is code on the server side
func CreateNewPost(c *gin.Context) {
title := strings.TrimSpace(c.PostForm("title"))
content := strings.TrimSpace(c.PostForm("content"))
latitude := c.PostForm("latitude")
longitude := c.PostForm("longitude")
imageFile, _ := c.FormFile("images")
replyTo := c.PostForm("reply_to")
private := c.PostForm("private") != ""
createdBy := c.PostForm("from")
language := c.Query("lang")
var (
imageFilename string = ""
user User
newPost Post
)
if title == "" && content == "" && (imageFile == nil || imageFile.Filename == "") {
if language == "fr" {
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "mssg": "Votre ping est vide !"})
} else {
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "mssg": "Your ping is empty!"})
}
return
}
....
Dart http.MultipartRequest works well with my implementation. However, I'm in France, and we have letters such as é à ç ö etc, so when filling my form in French with those characters, on the server side, the body parameters are empty ! I think it is a utf8 issue with http.MultipartRequest ?
Does anybody can help me?
This code doesn't work, the content field is reset to empty string
var url = Uri.parse( Application.backendBaseURL + route);
var request = new http.MultipartRequest('POST', url);
request.fields['content'] = 'à éviter, ça marche pas!';
if (files != null && files.length > 0)
request.files.addAll(files);
request.send().then((response) {
if (response.statusCode == 200) print("Uploaded!");
});
But if I write
request.fields['content'] = 'a eviter, ca marche pas!';
The content field is sent correctly to the backend API
This means there may be an issue with utf-8 fields, right ?
Can you post a pure-Dart reproduction, that includes server code as well?
Damn, I got this issue too...... I think this is imergency cause Not-English has seriously problem with http.MultipartRequest this class.
I am in China, I do exactly like @Eimji , with field contains Chinese such as 妈的,我日了, and the server side gots empty.
However I am not test on both Android or iOS side, at least, on iOS side we have this trouble.
I wanna suggested Flutter authors or it's contributors work on this issue quickly, cause flutter is groth very fast, but this basic package are still with so many bugs... Just report this, help solve it very soon.
BTW, @Eimji Did'u find any solution on this? #
Hello
I didn't find any solution. My backend implementation works (tested with Postman and browser) I tried many workarounds to fix the issue but no success. Due to deadlines in my dev planning, I finally implemented a trick in my Flutter application. Instead of sending one POST request with multipart I send two successive POST requests: one for text inputs and one for file inputs. Not the best workaround but it works!
Here is my app https://play.google.com/store/apps/details?id=com.orange.labs.spilhenn
You can also find the iOS version here
https://itunes.apple.com/fr/app/spilhenn/id1385377725
I will post a sample code in Dart for client and in Go for backend to reproduce the issue
@Eimji @jinfagang
In my flutter app, I commented on the following code, I got the Go backend to recognize it properly.
multipart_request.dart
/// Returns the header string for a field. The return value is guaranteed to
/// contain only ASCII characters.
String _headerForField(String name, String value) {
var header =
'content-disposition: form-data; name="${_browserEncode(name)}"';
// if (!isPlainAscii(value)) {
// header = '$header\r\n'
// 'content-type: text/plain; charset=utf-8\r\n'
// 'content-transfer-encoding: binary';
// }
return '$header\r\n\r\n';
}
Hello
I didn't find any solution. My backend implementation works (tested with Postman and browser) I tried many workarounds to fix the issue but no success. Due to deadlines in my dev planning, I finally implemented a trick in my Flutter application. Instead of sending one POST request with multipart I send two successive POST requests: one for text inputs and one for file inputs. Not the best workaround but it works!
Here is my app https://play.google.com/store/apps/details?id=com.orange.labs.spilhenn
You can also find the iOS version here
https://itunes.apple.com/fr/app/spilhenn/id1385377725I will post a sample code in Dart for client and in Go for backend to reproduce the issue
Did you find any answer to this? I am also facing the same
please follow my code, It's not working when upload file audio and video, please help me!
Map
"Authorization": "Bearer $token",
"Content-Type": "multipart/form-data"
};
var uri = Uri.parse(settings.baseUrl + "/update-introduce");
print(uri);
var request = new http.MultipartRequest("POST", uri);
// add header
request.headers.addAll(headers);
request.fields['bio'] = " Hello hi everybody ",
request.files.add(await http.MultipartFile.fromPath(
'audio_file', _formData['audio_file'].path));
request.files.add(await http.MultipartFile.fromPath(
'movie_file', _formData['movie_file'].path));
StreamedResponse response = await request.send().then((response) {
print("successful");
print(response.toString());
});
print(response.toString());
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
this is error show log
I/flutter ( 9636): null
E/flutter ( 9636): [ERROR:flutter/shell/common/shell.cc(184)] Dart Error: Unhandled exception:
E/flutter ( 9636): NoSuchMethodError: The getter 'stream' was called on null.
E/flutter ( 9636): Receiver: null
Does anybody can help me?
This code doesn't work, the content field is reset to empty stringvar url = Uri.parse( Application.backendBaseURL + route); var request = new http.MultipartRequest('POST', url); request.fields['content'] = 'à éviter, ça marche pas!'; if (files != null && files.length > 0) request.files.addAll(files); request.send().then((response) { if (response.statusCode == 200) print("Uploaded!"); });But if I write
request.fields['content'] = 'a eviter, ca marche pas!';
The content field is sent correctly to the backend API
This means there may be an issue with utf-8 fields, right ?
I'm getting the same error for Arabic.
It is sending the English text easily. But, I Can't send the Arabic.
any solution i face that in arabic
So I faced the same issue too (using utf8 / non-ascii charset) when doing http.MutipartRequest with slightly a different result:
HttpException: Unsupported contentTransferEncoding: binary
#0 new HttpMultipartFormDataImpl (package:http_server/src/http_multipart_form_data_impl.dart:36:7)
#1 HttpMultipartFormDataImpl.parse (package:http_server/src/http_multipart_form_data_impl.dart:86:12)
#2 HttpMultipartFormData.parse (package:http_server/src/http_multipart_form_data.dart:70:33)
#3 HttpBodyHandlerImpl.process.asFormData.<anonymous closure> (package:http_server/src/http_body_impl.dart:100:48)
#4 _MapStream._handleData (dart:async/stream_pipe.dart:229:21)
---snip---
In my case the dart backend threw Unsupported contentTransferEncoding: binary and a good chap came to my rescue: https://github.com/dart-lang/http_server/commit/1cf78534e681f21d75c2d47659d9f9249be3d039
So I just changed the source to the commit id directly and it works ok now.
#http_server: ^0.9.8+3
http_server:
git:
url: https://github.com/dart-lang/http_server.git
ref: df31d20
sotisoti@debian:~/dart_api$ pub get
Resolving dependencies... (2.6s)
* http_server 0.9.8+4-dev from git https://github.com/dart-lang/http_server.git at df31d2 (was 0.9.8+3)
Changed 1 dependency!
@sotisoti
I'm also having this problem with a backend made with Angel Framework
Most helpful comment
Hello
I didn't find any solution. My backend implementation works (tested with Postman and browser) I tried many workarounds to fix the issue but no success. Due to deadlines in my dev planning, I finally implemented a trick in my Flutter application. Instead of sending one POST request with multipart I send two successive POST requests: one for text inputs and one for file inputs. Not the best workaround but it works!
Here is my app https://play.google.com/store/apps/details?id=com.orange.labs.spilhenn
You can also find the iOS version here
https://itunes.apple.com/fr/app/spilhenn/id1385377725
I will post a sample code in Dart for client and in Go for backend to reproduce the issue