Dart - HTTPClient 下载文件到字符串

Dart - HTTPClient download file to string

在我目前正在开发的 Flutter/Dart 应用程序中,需要从我的服务器下载大文件。但是,我需要做的不是将文件存储在本地存储中,而是解析其内容并使用它一次性。我认为实现此目的的最佳方法是实现我自己的 StreamConsumer 并覆盖相关方法。这是我到目前为止所做的

import 'dart:io';
import 'dart:async';

class Accumulator extends StreamConsumer<List<int>>
{
 String text = '';

 @override
  Future<void> addStream(Stream<List<int>> s) async
  {
   print('Adding'); 
   //print(s.length); 
   return; 
  }

 @override 
 Future<dynamic> close() async
 {
  print('closed'); 
  return Future.value(text);
 }
}

Future<String> fileFetch() async
{
 String url = 'https://file.io/bse4moAYc7gW'; 
 final HttpClientRequest request = await HttpClient().getUrl(Uri.parse(url));
 final HttpClientResponse response = await request.close();
 return await response.pipe(Accumulator());
}

Future<void> simpleFetch() async
{
 String url = 'https://file.io/bse4moAYc7gW'; 
 final HttpClientRequest request = await HttpClient().getUrl(Uri.parse(url));
 final HttpClientResponse response = await request.close();
 await response.pipe(File('sample.txt').openWrite());
 print('Simple done!!');  
}

void main() async 
{
 print('Starting'); 
 await simpleFetch(); 
 String text = await fileFetch();
 print('Finished! $text');
}

当我在 VSCode 中 运行 这就是我得到的输出

Starting
Simple done!! //the contents of the file at https://file.io/bse4moAYc7gW are duly saved in the file 
sample.txt
Adding //clearly addStream is being called
Instance of 'Future<int>' //I had expected to see the length of the available data here
closed //close is clearly being called BUT
Finished! //back in main()

我对这里的潜在问题的理解仍然很有限。我的期待

  1. 我本来想用addStream来积累正在下载的内容,直到
  2. 没有更多内容可下载,此时将调用 close,程序将显示 exited

为什么 addStream 显示 instance of... 而不是可用内容的长度? 尽管 VSCode 调试控制台确实显示 exited,但这种情况会在显示 closed 几秒钟后发生。我认为这可能是必须调用 super.close() 的问题,但事实并非如此。我在这里做错了什么?

我本来打算删除这个问题,但为了其他试图做类似事情的人的利益,决定把它留在这里并给出答案。

要注意的关键点是对 Accumulator.addStream 的调用就是这样做的 - 它提供了一个要 listened 的流,没有要读取的实际数据。你接下来要做的是这个

void whenData(List<int> data)
{
 //you will typically get a sequence of one or more bytes here.
 for(int value in data)
 {
  //accumulate the incoming data here
 } 
 return;
} 

function void whenDone()
{
 //now that you have all the file data *accumulated* do what you like with it
} 

@override
Future<void> addStream(Stream<List<int>> s) async
{
 s.listen(whenData,onDone:whenDone);
 //you can optionally ahandler for `onError`
}