Flutter HTTP 请求使用 xml 正文发送

Posted

技术标签:

【中文标题】Flutter HTTP 请求使用 xml 正文发送【英文标题】:Flutter HTTP request send using xml body 【发布时间】:2020-02-12 09:52:49 【问题描述】:

我正在尝试在 Flutter/Dart 中处理 HTTP 请求(在本例中使用 SEARCH 方法过滤 WebDAV 服务器 (Nextcloud) 上的某些文件)需要在请求的正文中发送 XML 数据。

[x] 可以通过 --data 参数在终端上使用 cURL 执行命令:

curl -u user:pass -X SEARCH 'https://host123.com.br/remote.php/dav' -H "content-Type: text/xml" --data '<?xml version="1.0" encoding="UTF-8"?><d:searchrequest xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns"><d:basicsearch><d:select><d:prop><d:displayname/></d:prop></d:select><d:from><d:scope><d:href>/files/wprech</d:href><d:depth>infinity</d:depth></d:scope></d:from><d:where><d:and><d:or><d:eq><d:prop><d:getcontenttype/></d:prop><d:literal>image/png</d:literal></d:eq><d:eq><d:prop><d:getcontenttype/></d:prop><d:literal>image/jpg</d:literal></d:eq><d:eq><d:prop><d:getcontenttype/></d:prop><d:literal>video/mp4</d:literal></d:eq></d:or></d:and></d:where><d:orderby/></d:basicsearch></d:searchrequest>'

[x] 也可以通过 Postman 应用工作:

[ ] 无法使用 Flutter/Dart 对 xml 正文执行此请求。 我们使用 DIO pkg 这个项目的所有其他 HTTP 请求,它工作正常,但问题是。用它发送 xml 正文。最接近的代码如下:

void _list() async 
final prefs = await SharedPreferences.getInstance();

var us = prefs.getString('id') ?? '';
var sn = prefs.getString('password') ?? '';

String basicAuth = 'Basic ' + base64Encode(utf8.encode('$us:$sn'));

try 
  Dio dio = new Dio();
  dio.options.method = 'SEARCH';
  dio.options.responseType = ResponseType.plain;
  dio.options.headers = 
    HttpHeaders.authorizationHeader: basicAuth,
    'content-Type': 'text/xml'
  ;
  String data =
      '<?xml version="1.0" encoding="UTF-8"?><d:searchrequest xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns"><d:basicsearch><d:select><d:prop><d:displayname/></d:prop></d:select><d:from><d:scope><d:href>/files/wprech</d:href><d:depth>infinity</d:depth></d:scope></d:from><d:where><d:and><d:or><d:eq><d:prop><d:getcontenttype/></d:prop><d:literal>image/png</d:literal></d:eq><d:eq><d:prop><d:getcontenttype/></d:prop><d:literal>image/jpg</d:literal></d:eq><d:eq><d:prop><d:getcontenttype/></d:prop><d:literal>video/mp4</d:literal></d:eq></d:or></d:and></d:where><d:orderby/></d:basicsearch></d:searchrequest>';

  Response response = await dio.request(
      "https://host123.com.br/remote.php/dav",
      data: data);

  print(response);
 catch (e) 
  print(e);

服务器响应在 400、404、500 和 501 之间变化,具体取决于其发送方式:

I/flutter ( 6767): DioError [DioErrorType.RESPONSE]: Http status error [400]

有什么帮助吗? :)

【问题讨论】:

你试过package:http吗?用正确的方法创建一个BaseRequest,然后send()它。 @RichardHeap 找不到任何使用包的示例:http 并发送 xml 正文和自定义方法(如“搜索”)。有吗? 不,但是很容易拼凑起来。 (正文是 XML 并没有什么特别之处 - 它只是一个字符串。)作为答案发布。 【参考方案1】:

用更简单的package:http 版本进行实验。

import 'dart:convert';
import 'dart:io';

import 'package:http/http.dart' as http;

main() async 
  var username = 'foo';
  var password = 'B@r!';
  var credential = base64.encode(utf8.encode('$username:$password'));
  var client = http.IOClient();

  var request = http.Request(
    'SEARCH',
    Uri.parse('https://host123.com.br/remote.php/dav'),
  );
  request.headers.addAll(
    HttpHeaders.authorizationHeader: 'Basic $credential',
    'content-type': 'text/xml' // or text/xml;charset=utf-8
  );

  var xml = '<?xml version="1.0" encoding="UTF-8"?>...';
  // either
  request.body = xml;
  // which will encode the string to bytes, and modify the content-type header, adding the encoding
  // or
  // request.bodyBytes = utf8.encode(xml);
  // which gives you complete control over the character encoding

  var streamedResponse = await client.send(request);
  print(streamedResponse.statusCode);

  var responseBody =
      await streamedResponse.stream.transform(utf8.decoder).join();
  print(responseBody);
  client.close();

【讨论】:

我使用了你的 sn-p,现在它返回状态码 207,与邮递员返回的代码相同,这是一个进步。如何按预期打开响应数据?尝试在 print(streamedResponse.xxxx) 上自动完成,但没有返回响应正文或数据。 StreamedResponse 使用名为 stream 的 getter 自动完成,这是一个 ByteStream。您可能需要一个字符串,而不是字节流,因此您必须将字节转换为具有字符编码的字符,然后将字符串的任何部分组合成一个。答案已更新。 终于成功了!不能感谢你。如果你在这附近,我会给你买啤酒?。再次感谢。

以上是关于Flutter HTTP 请求使用 xml 正文发送的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中使用 JSON 正文发出 http DELETE 请求?

如何在 Flutter/Dart 中使用 url 编码的标头和正文发出 HTTP POST 请求

Flutter 中使用 Http Post 上传正文

如何将 json 列表传递给 Flutter 中的 http 请求(post)正文?

如何将图像文件传递到 Flutter 中的 Http 请求(POST)正文?

如何将 ArrayList 项传递给 Flutter 中的 http 请求(post)正文?