Флаттер http MultipartRequest поле не может быть китайских символов? - PullRequest
0 голосов
/ 26 мая 2018

Я пытаюсь отправить форму на сервер, и вот код:

ar request = new http.MultipartRequest("POST", _uri);
request.fields['user_acc'] = _userAcc;
// this issue should be solve
request.fields['user_nick_name'] = '中文名字';
request.fields['user_password'] = _password;

Но сторона сервера в поле user_nick_name всегда имеет значение NULL, обратите внимание, что всегда , ноЯ изменяю это на английский, что сервер может получить это.Я тестирую на почтальоне, сервер может получить китайский язык правильно, так что это проблема MultipartRequest по этой проблеме.

Мой вопрос: Почему команда Дартс или Флаттер так небрежно относится к этой столь важной базовой библиотеке? Они даже не считают об этом просто вопросом.Я открыл вопрос о github, но никто не ответил, я думаю, что команда готова.Поэтому я спрашиваю разработчиков в сообществе, как решить эту проблему в любом случае?

[ОБНОВЛЕНИЕ] Как любезно предложили люди, я обновляю свой сервер golang сейчас, если у кого-то еще возникла эта проблема, выможет не будет отвечать и предложения.

func HandleUserRegister(context *gin.Context) {

userAcc := context.PostForm("user_acc")
userAvatar := context.PostForm("user_avatar")
userNickName := context.PostForm("user_nick_name")
userPassword := context.PostForm("user_password")
userPhone := context.PostForm("user_phone")
userEmail := context.PostForm("user_email")
userGender := context.PostForm("user_gender")
userSign := context.PostForm("user_sign")

userType := context.PostForm("user_type")
userTypeInt, _ := strconv.Atoi(userType)

log.Infof("userAcc: %s, userNickName: %s, userPassword: %s", userAcc, userNickName, userPassword)}

Это основано на джине, и эта функция решает API.Если кто-то хочет помочь, пожалуйста, помогите мне разобраться.

ОК!Я обновляю вопрос сейчас, , потому что это действительно странно! .Я выполнил эти тесты:

  1. Отправка мультиформата через Flutter на сервер Django, он корректно получает данные, заполненные на китайском языке;
  2. Отправка мультиформной информации через Postman, сервер golang (gin) правильно переводит китайский язык;
  3. Публикация мультиформных данных через сервер Flutter на golang (gin) gots Китайское поле null ;

Для более подробной информации я веду заголовки с моего сервера для обоихпочтальон (нормальный) и флаттер (ненормальный):

почтальон : request header: map[Content-Type:[multipart/form-data; boundary=--------------------------022341683711652813100488] Postman-Token:[855646d7-5bea-4b8f-b8df-81366226cd49] User-Agent:[PostmanRuntime/7.1.1] Content-Length:[422] Connection:[keep-alive] Cache-Control:[no-cache] Accept:[*/*] Accept-Encoding:[gzip, deflate]] флаттер : request header: map[User-Agent:[Dart/2.0 (dart:io)] Content-Type:[multipart/form-data; boundary=dart-http-boundary-.XUeYeqXpg4Yfyh8QhH1T5JB4zi_f3WxX9t7Taxhw91EFqhyki4] Accept-Encoding:[gzip] Content-Length:[574]]

Кто-нибудь может заметить разницуи дайте мне знать, как изменить это сделать сервер может получать китайские иероглифы?

Ответы [ 4 ]

0 голосов
/ 30 мая 2018

Я сейчас решил это.Спасибо Ричарду и Дэнни за помощь.

1.Причина этого

Независимо от того, что происходит, но на самом деле это не только односторонняя проблема, мы не можем сказать, что это флаттер или ошибка.Но комбинация Flutter + Go server как раз может получить эту проблему.Причиной, по которой я до сих пор не уверен, но должна быть какая-то неправильная голова (почтальон может сделать это правильно);

2.Решение

Нам нужно не только знать, почему, но и как его решить.Вот что я делаю:

Не используйте официальный http-пакет .Используя dio, который является расширением пакета Dart.ссылка: https://pub.dartlang.org/packages/dio

Это более чистый и простой в использовании, поэтому мой код становится следующим:

 FormData _formData = new FormData.from({
  "user_acc": _userAcc,
  "user_nick_name": _userNickName,
  'user_password': _password,
});

Dio dio = new Dio();
Response response = await dio.post(usersUrl, data: _formData);
print(response.data);

Я не могу сейчас публиковать неанглийские слова:

INFO[0668] userAcc: ww, userNickName: 小鹿叮叮婴儿湿巾手口专用80抽湿纸巾婴儿湿巾婴儿100抽带盖批发【原价】34.90元【券后】9.9元【省】25元【复制此信息打开手机淘宝即可查看并下单】¥Tnsx0E77pFs¥【必买理由】新品预售80抽*3仙女联盟,更多优惠fd.loliloli.pro    , userPassword: ww 

INFO [0671] пользователь существует.

0 голосов
/ 26 мая 2018

@ DannyTuppeny правильный.Это проблема сервера.

При запросе включения поля, не входящего в ASCII, в запрос, состоящий из нескольких частей, библиотека Dart правильно оборачивает его двоичной кодировкой передачи содержимого.

  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';
  }

(Почтальон не отправляет и просто отправляет строку в кодировке utf8 без заголовков.)

Dart / ASCII выглядит следующим образом:

--dart-http-boundary-HjDS88CmQicdgd8VaHSwPqJK8iR4H6rTG3LovSZy-QXGpU7pAB0
content-disposition: form-data; name="test"

stackover
--dart-http-boundary-HjDS88CmQicdgd8VaHSwPqJK8iR4H6rTG3LovSZy-QXGpU7pAB0

Dart / non-ASCII выглядит следующим образом:

First boundary: --dart-http-boundary-58NU6u6_Fo22xjH8H7yPCtKuoKgB+A8+RTJ82iIK1gs3nnGMLlp\r\n
Encapsulated multipart part:  (text/plain)
    content-disposition: form-data; name="test"\r\n
    content-type: text/plain; charset=utf-8\r\n
    content-transfer-encoding: binary\r\n\r\n
    Line-based text data: text/plain
        \344\270\255\346\226\207\345\220\215\345\255\227
Boundary: \r\n--dart-http-boundary-58NU6u6_Fo22xjH8H7yPCtKuoKgB+A8+RTJ82iIK1gs3nnGMLlp\r\n

Таким образом, проблема в том, что сервер не может развернуть значение из инкапсуляции.

EDIT Вот трассировка Почтальона, которую я захватил вчера.Он мультиформный, но не может добавить заголовок кодировки типа контента, несмотря на то, что поле не является ASCII.

MIME Multipart Media Encapsulation, Type: multipart/form-data, Boundary: "--------------------------595246000077585285134204"
    [Type: multipart/form-data]
    First boundary: ----------------------------595246000077585285134204\r\n
    Encapsulated multipart part: 
        Content-Disposition: form-data; name="name"\r\n\r\n
        Data (12 bytes)

0000  e4 b8 ad e6 96 87 e5 90 8d e5 ad 97               ............
            Data: e4b8ade69687e5908de5ad97
            [Length: 12]
    Last boundary: \r\n----------------------------595246000077585285134204--\r\n
0 голосов
/ 30 мая 2018

Проблема, кажется, в formdata.go части multipart.Go предполагает, что любая составная часть с заголовком Content-Type является файлом (а не полем).Однако, зная это, вы можете изменить код своего сервера следующим образом:

func main() {
    r := gin.Default()
    r.POST("/sotest", func(c *gin.Context) {

        formValue := c.PostForm("form_value")

        if formValue == "" {
            formFile, _ := c.FormFile("form_value")
            file, _ := formFile.Open()
            b1 := make([]byte, formFile.Size)
            file.Read(b1)
            formValue = string(b1)
        }

        c.JSON(200, gin.H{
            "status":    "posted",
            "formValue": formValue,
        })
    })
    r.Run() // listen and serve on 0.0.0.0:8080
}

Когда вы обнаружите, что PostForm возвращает пустую строку, вы знаете, что Go обработал поле как файл, и в этом случае выможет открыть и прочитать «файл» и декодировать его как строку utf-8, которая нам известна.Очевидно, что вы можете инкапсулировать тест "try as PostForm и, если он пустой, try as FormFile", в функцию.

Если вы не хотите проверять наличие пустой строки на сервере, вы можете изменитьваш код конца Dart всегда кодирует utf-8 даже строки не ascii с

request.files.add(
  new http.MultipartFile.fromBytes(
    'some_form_value_name',
    utf8.encode('the string value'),
    contentType: new MediaType('text', 'plain', {'charset': 'utf-8'}),
  ),
);

и считывает их на сервере с помощью метода Open / Read / string.

0 голосов
/ 26 мая 2018

Я проверил, отправив сообщение на httpbin, и ответ предполагает, что символы были отправлены правильно:

MultipartRequest

"user_nick_name": "\u4e2d \ u540d \ u5b57 "

Я пробовал использовать как Stable v1 SDK, так и v2 SDK от Flutter.Возможно ли проблема на сервере?Вы пытались использовать что-то вроде Fiddler для захвата того, что на самом деле отправляется?

Редактировать: Я предполагаю, что ваш код на стороне сервера неправильно читает данные как данные MultipartForm (например, вы должныиспользовать ParseMultipartForm и читать из MultipartForm).

...