【问题标题】:How do I use StreamedRequest in Dart http library to upload a file?如何在 Dart http 库中使用 StreamedRequest 上传文件?
【发布时间】:2018-07-05 15:58:23
【问题描述】:

我想通过这样的非multipart/form-data 请求上传文件:

POST http://127.0.0.1/upload
Cache-Control: no-cache

< /path/to/file/in/disk

(我进行了测试,它成功地将文件从 JetBrain Rider 的 REST 客户端上传到了我的 REST 端点。)

http 包中有一个StreamedRequest 类,但我没有找到任何构造函数或设置器来插入字节流或文件内容。

如何使用StreamedRequest 在 Dart 中上传文件?

【问题讨论】:

    标签: rest http file-upload dart


    【解决方案1】:

    我只是要发布 phqb 的解决方案,以防 pastebin 链接失效:

    final file = new File(filePath);
    
    final streamedRequest =
        new http.StreamedRequest('POST', Configurations.getUserContentsApiUri('/upload'))
          ..headers.addAll({
            'Cache-Control': 'no-cache',
            'Authorization': 'Bearer $uploadToken',
          });
    streamedRequest.contentLength = await file.length();
    file.openRead().listen((chunk) {
      print(chunk.length);
      streamedRequest.sink.add(chunk);
    }, onDone: () {
      streamedRequest.sink.close();
    });
    
    await streamedRequest.send();
    print('after response');
    

    【讨论】:

    【解决方案2】:

    在我使用的一些旧代码中

      /// Send a POST request to the Docker service.
      Future<http.ByteStream> _streamRequestStream(
          String path, Stream<List<int>> stream,
          {Map<String, String> query}) async {
        assert(stream != null);
        final url = serverReference.buildUri(path, query);
        final request = new http.StreamedRequest('POST', url)
          ..headers.addAll(headersTar);
        stream.listen(request.sink.add);
        final http.BaseResponse response =
            await request.send().then(http.Response.fromStream);
        if (response.statusCode < 200 || response.statusCode >= 300) {
          throw new DockerRemoteApiError(
              response.statusCode, response.reasonPhrase, null);
        }
        return (response as http.StreamedResponse).stream;
      }
    

    这可能会做你想做的事

    https://github.com/bwu-dart/bwu_docker/blob/master/lib/src/remote_api.dart#L160-L178

    它使用http 包

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

    【讨论】:

    • 谢谢,请求成功,文件已上传。但我如何听取回应? await request.send() 似乎永远不会完成。 (在这个script 中,print 语句从未被执行过。)
    • 我想通了。关闭文件流的onDone 上的sink 解决了这个问题。
    • 如何根据pub.dev/documentation/http/latest/http/…给streamedRequest.stream写信?我试过streamedRequest.sink.addStream(),但没有用。
    • 和我一样 request.sink.add 怎么样?
    • 但是我如何使用这个带有 streamedRequest 的主体发送 POST 请求,例如 body: {'hello': 'world'}。 sink.add() 只接受 List 如何发送对象?
    【解决方案3】:

    更新:

    发布此消息一天后,我意识到这实际上并没有测量 上传 进度,而只是 读取 来自本地 JSON 有效负载的字节的进度,即几乎是瞬间的。如果/当我弄清楚如何实际衡量上传进度时,我会更新这个答案。


    原答案:

    这对我有用:

    import 'dart:convert';
    import 'package:http/http.dart' as http;
    
    // ...
    
    final jsonPayload = {'base64File': 'abc123', 'something': 'else'};
    
    // We are using a StreamedRequest so we can track the upload progress
    final streamedRequest = http.StreamedRequest("POST", apiUri);
    streamedRequest.headers['content-type'] = 'application/json';
    
    // Length transferred (to calculate upload progress)
    var transferredLength = 0;
    // Upload progress (from 0.0 to 1.0)
    var uploadProgress = 0.0;
    // The stringified JSON payload
    var stringEncodedPayload = jsonEncode(jsonPayload);
    // Total length (to calculate upload progress)
    var totalLength = stringEncodedPayload.length;
    
    // Create a stream of the payload string
    Stream.value(stringEncodedPayload)
      // Transform the string-stream to a byte stream (List<int>)
      .transform(utf8.encoder)
      // Start reading the stream in chunks, submitting them to the streamedRequest for upload
      .listen((chunk) {
        transferredLength += chunk.length;
        uploadProgress = transferredLength / totalLength;
        print("Chunk: ${chunk.length}, transferred: $transferredLength, progress: $uploadProgress");
        streamedRequest.sink.add(chunk);
      }, onDone: () {
        print("Done. Total: $totalLength, transferred: $transferredLength, progress: $uploadProgress");
        streamedRequest.sink.close();
      });
    
    final result = await client.send(streamedRequest).then(http.Response.fromStream);
    
    
    print("----------->");
    print(result.statusCode);
    print(result.body);
    print("<-----------");
    

    输出:

    flutter: Chunk: 1024, transferred: 1024, progress: 0.0008807503580198599
    flutter: Chunk: 1024, transferred: 2048, progress: 0.0017615007160397197
    flutter: Chunk: 1024, transferred: 3072, progress: 0.0026422510740595796
    ...
    flutter: Chunk: 1024, transferred: 1159168, progress: 0.9970094052784814
    flutter: Chunk: 1024, transferred: 1160192, progress: 0.9978901556365013
    flutter: Chunk: 1024, transferred: 1161216, progress: 0.9987709059945211
    flutter: Chunk: 1024, transferred: 1162240, progress: 0.9996516563525409
    flutter: Chunk: 405, transferred: 1162645, progress: 1.0
    flutter: Done. Total: 1162645, transferred: 1162645, progress: 1.0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 2015-11-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多