首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在dart中解析http多部分/混合响应(颤振)

如何在dart中解析http多部分/混合响应(颤振)
EN

Stack Overflow用户
提问于 2022-05-18 18:21:58
回答 1查看 186关注 0票数 0

我想解析一个多部分/混合http响应。对于我的问题,我找不到任何可用的sdk或插件。我已经尝试过mime包,它有一个MimeMultipartTransformer,但是它返回一个异常Bad multipart ending

要解析示例内容的多部分/混合响应字符串(从utf8二进制文件转换而来):

代码语言:javascript
运行
复制
HTTP/1.1 200 OK
Content-Type: multipart/mixed; boundary="7b1596fc4940bc1be725ad67f11ec1c4"
Date: Thu, 07 Nov 2013 15:10:16 GMT
Server: CouchDB (Erlang OTP)
Transfer-Encoding: chunked

--7b1596fc4940bc1be725ad67f11ec1c4
Content-Type: application/json

{
    "_id": "SpaghettiWithMeatballs",
    "_rev": "1-917fa23",
    "_revisions": {
        "ids": [
            "917fa23"
        ],
        "start": 1
    },
    "description": "An Italian-American delicious dish",
    "ingredients": [
        "spaghetti",
        "tomato sauce",
        "meatballs"
    ],
    "name": "Spaghetti with meatballs"
}
--7b1596fc4940bc1be725ad67f11ec1c4
Content-Type: multipart/related; boundary="a81a77b0ca68389dda3243a43ca946f2"

--a81a77b0ca68389dda3243a43ca946f2
Content-Type: application/json

{
    "_attachments": {
      "recipe.txt": {
          "content_type": "text/plain",
          "digest": "md5-R5CrCb6fX10Y46AqtNn0oQ==",
          "follows": true,
          "length": 87,
          "revpos": 7
      }
    },
    "_id": "SpaghettiWithMeatballs",
    "_rev": "7-474f12e",
    "_revisions": {
        "ids": [
            "474f12e",
            "5949cfc",
            "00ecbbc",
            "fc997b6",
            "3552c87",
            "404838b",
            "5defd9d",
            "dc1e4be"
        ],
        "start": 7
    },
    "description": "An Italian-American delicious dish",
    "ingredients": [
        "spaghetti",
        "tomato sauce",
        "meatballs",
        "love"
    ],
    "name": "Spaghetti with meatballs"
}
--a81a77b0ca68389dda3243a43ca946f2
Content-Disposition: attachment; filename="recipe.txt"
Content-Type: text/plain
Content-Length: 87

1. Cook spaghetti
2. Cook meetballs
3. Mix them
4. Add tomato sauce
5. ...
6. PROFIT!

--a81a77b0ca68389dda3243a43ca946f2--
--7b1596fc4940bc1be725ad67f11ec1c4
Content-Type: application/json; error="true"

{"missing":"3-6bcedf1"}
--7b1596fc4940bc1be725ad67f11ec1c4--

这是我的测试代码:

代码语言:javascript
运行
复制
String auth = _generateauth(couchUsername, couchPassword);
    String url = couchServer +
        "/" +
        Uri.encodeComponent(couchDBName) +
        "/" +
        Uri.encodeComponent("patient/1001") +
        "?open_revs=" +
        Uri.encodeComponent("""["1-6bb2dd39beefd1dd2ae1f47c01caea37",
"2-logi",
"2-712b79fb62e64bbf3eab6c009334fb60",
"3-flower",
"4-bloom",
"3-b0c4b3b87373a410c4ad3710a39d7f81"
]""") +
        "&latest=true";
    http.Client client = http.Client();
    http.Request rq = http.Request("GET", Uri.parse(url));
    rq.headers.addAll({"Authorization": auth});
    http.StreamedResponse sr = await client.send(rq);
    if (sr.statusCode != 200) throw Exception("Server Error!");
    if (sr.headers["server"] == null ||
        !sr.headers["server"]!.contains("CouchDB"))
      throw Exception("Invalid Server: Invalid Transfer Encoding");

    print(sr.headers);
    RegExp boundaryget = RegExp('boundary="(.+)"');
    String contentType = sr.headers["content-type"].toString();

    final match = boundaryget.firstMatch(contentType);
    String boundary = match?.group(1) as String;

    List<int> completeResponse = await sr.stream.toBytes();
    List<List<int>> cr = [completeResponse];

    Stream<MimeMultipart> mm =
        MimeMultipartTransformer(boundary).bind(Stream.fromIterable(cr));
    mm.listen((event) {
      print(event);
    });

如有任何反馈,将不胜感激。

EN

回答 1

Stack Overflow用户

发布于 2022-05-18 20:22:28

我已经解决了我的问题。

首先,您将导入以下软件包:

代码语言:javascript
运行
复制
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import "package:http/http.dart" as http;
import 'package:mime/mime.dart';

这是密码:

代码语言:javascript
运行
复制
 Future<void> openRevs() async {
    String auth = _generateauth(couchUsername, couchPassword);
    String url = couchServer +
        "/" +
        Uri.encodeComponent(couchDBName) +
        "/" +
        Uri.encodeComponent("patient/1001") +
        "?open_revs=" +
        Uri.encodeComponent("""["1-6bb2dd39beefd1dd2ae1f47c01caea37",
"2-logi",
"2-712b79fb62e64bbf3eab6c009334fb60",
"3-flower",
"4-bloom",
"3-b0c4b3b87373a410c4ad3710a39d7f81"
]""") +
        "&latest=true";
    http.Client client = http.Client();
    http.Request rq = http.Request("GET", Uri.parse(url));
    rq.headers.addAll({"Authorization": auth});
    http.StreamedResponse sr = await client.send(rq);
    if (sr.statusCode != 200) throw Exception("Server Error!");
    if (sr.headers["server"] == null ||
        !sr.headers["server"]!.contains("CouchDB"))
      throw Exception("Invalid Server: Not a CouchDB Server!");

    print(sr.headers);

    // Generate REGEX to get boundary from content-type header
    RegExp boundaryget = RegExp('boundary="(.+)"');
    String contentType = sr.headers["content-type"].toString();

    // Get the boundary
    final match = boundaryget.firstMatch(contentType);
    String boundary = match?.group(1) as String;

    // Get the completed response from the server
    List<int> completeResponse = await sr.stream.toBytes();

    // Create a list for stream creation..
    List<List<int>> cr = [completeResponse];

    // generate MimeMultipart Stream
    Stream<MimeMultipart> mm =
        MimeMultipartTransformer(boundary).bind(Stream.fromIterable(cr));

    // We put the parsed responses here...
    List<MimeMultipart> mixedResponse = [];
    List<MimeMultipart> relatedResponse = [];

    // Completer. So we can wait for the two response results.
    Completer<bool> allDone = Completer<bool>();
    Completer<bool> relatedComplete = Completer<bool>();

    mm.listen((event) async {
      String contentType = event.headers["content-type"].toString();

      // If content-type is multipart/related, we need to reparse it with MimeMultiPartTransformer
      if (contentType.contains("multipart/related")) {
        List<List<int>> data = await event.toList();
        Stream<List<int>> myStream = Stream.fromIterable(data);

        final match = boundaryget.firstMatch(contentType);
        boundary = match?.group(1) as String;

        Stream<MimeMultipart> responseData =
            MimeMultipartTransformer(boundary).bind(myStream);

        responseData.listen((event) {
          // Add to relatedResponse
          relatedResponse.add(event);
        }, onDone: () => relatedComplete.complete(true), 
        onError: (er) => relatedComplete.complete(false));
      } else {
        // Add to mixedResponse
        mixedResponse.add(event);
      }
    }, onDone: () => allDone.complete(true), onError: (e) => allDone.complete(false));

    // Lets wait for the results...
    await relatedComplete.future;
    await allDone.future;

    // Here are the results.
    print("Mixed Response Length: " + mixedResponse.length.toString());
    print("Related Response Length: " + relatedResponse.length.toString());
    for (MimeMultipart response in mixedResponse) {
      print("Headers: " + response.headers.toString());
      List<String> body = await response.single
          .asStream()
          .map(((event) => utf8.decode(event, allowMalformed: true)))
          .toList();
      print("Content Body: " + body[0].toString());
    }
    for (MimeMultipart response in relatedResponse) {
      print(response.headers);
      List<String> body = await response.single
          .asStream()
          .map(((event) => utf8.decode(event, allowMalformed: true)))
          .toList();
      print("Content Body: " + body[0].toString());

      // That's all.
    }
  }

调试控制台将显示如下:

代码语言:javascript
运行
复制
flutter: {x-couchdb-body-time: 0, x-couch-request-id: b2930f11cd, content-type: multipart/mixed; boundary="b9c676d8e38719f6db939e000e1584f4", transfer-encoding: chunked, date: Wed, 18 May 2022 20:08:11 GMT, server: CouchDB/3.2.0 (Erlang OTP/22)}
flutter: Mixed Response Length: 2
flutter: Related Response Length: 2
flutter: Headers: {content-type: application/json}
flutter: Content Body: {"_id":"patient/1001","_rev":"5-d1eea3934c7a179636ca3021e30615cf","_deleted":true}
flutter: Headers: {content-type: application/json; error="true"}
flutter: Content Body: {"missing":"2-logi"}
flutter: {content-type: application/json}
flutter: Content Body: {"_id":"patient/1001","_rev":"5-738ce01d9989bc16084b01572871d9e6","first_name":"Amees - Sun & Moon","_attachments":{"Screen Shot 2022-05-17 at 11.32.22 AM.png":{"content_type":"image/png","revpos":4,"digest":"md5-irm/EL7L1BiKmfimBIWLIw==","length":156857,"follows":true}}}
flutter: {content-disposition: attachment; filename="Screen Shot 2022-05-17 at 11.32.22 AM.png", content-type: image/png, content-length: 156857}
flutter: Content Body: �PNG
\^Z

我想我需要自己完整地编写解析器。感谢省道开发人员,他们开发了这个插件,为我节省了很多时间。

https://pub.dev/packages/mime

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72294203

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档