Asynchronous 如何正确下载和保存图像列表?

Asynchronous 如何正确下载和保存图像列表?,asynchronous,dart,Asynchronous,Dart,我有一个URL的图像列表,想下载并保存每个图像。不幸的是,由于堆空间耗尽,我一直收到内存不足异常。上次尝试保存了两个映像,然后抛出“耗尽堆空间,尝试分配33554464字节” 我的代码如下所示。逻辑似乎是正确的,但我相信异步调用可能是错误的。是否有一些调整,我应该使下载顺序?还是我应该使用另一种方法 import'package:http/http.dart'作为http; 导入“dart:io”; main(){ //loc是一组有效的URL // ... 位置forEach(检索图像) }

我有一个URL的图像列表,想下载并保存每个图像。不幸的是,由于堆空间耗尽,我一直收到内存不足异常。上次尝试保存了两个映像,然后抛出“耗尽堆空间,尝试分配33554464字节”

我的代码如下所示。逻辑似乎是正确的,但我相信异步调用可能是错误的。是否有一些调整,我应该使下载顺序?还是我应该使用另一种方法

import'package:http/http.dart'作为http;
导入“dart:io”;
main(){
//loc是一组有效的URL
// ...
位置forEach(检索图像)
}
无效检索图像(字符串位置){
Uri=Uri.parse(位置);
字符串名称=uri.pathSegments.last;
打印(“读取$location”);
http.readBytes(location).then((image)=>saveImage(name,image));
} 
void saveImage(字符串名称、变量数据){
新文件(“${name}”)
..writeAsBytesSync(数据);
印刷品(姓名);
}

如果要按顺序下载,可以切换到。该枚举器通过一个集合对每个枚举器执行一个函数,但在继续下一个枚举之前,将等待函数返回完成的未来。反过来,它返回一个一旦最终迭代完成就完成的未来

而不是

loc.forEach(检索图像);
使用

Future.forEach(loc,retrieveImage);
然后确保
retrieveImage
返回未来:

未来检索图像(字符串位置){
Uri=Uri.parse(位置);
字符串名称=uri.pathSegments.last;
打印(“读取$location”);
返回http.readBytes(location)。然后((image)=>saveImage(name,image));
}

如果@DannyTuppeny s不能解决您的问题,您可以增加堆大小。 我认为这应该是做这件事的标志

old_gen_heap_size: 1024 (Max size of old gen heap size in MB,e.g: --old_gen_heap_size=1024 allows up to 1024MB old gen heap)

还提到了
--新的\u gen\u heap\u大小
,但
省道--打印标志
没有列出它。 我不知道这是否得到支持以及它的作用

我在您的代码中看到的问题是,几乎一次就开始下载所有图像,当它们被接收时,它们使用堆内存。而且@DannyTupeny的代码不会改变这一点

您可以通过在以前的请求完成时仅调用新请求来限制并发下载的文件数量,也可以在接收数据时使用流将数据写入文件,这样就不需要在内存中完全缓冲。 我自己还没有这样做过,至少在周日之前没有时间去调查,但也许其他人可以提供更多的细节

要将传入的数据直接重定向到一个文件,而不在内存中缓冲整个文件,这应该可以工作,但我无法重现内存不足的问题,所以我不能确定

导入'dart:io'作为io;
将“dart:async”导入为异步;
导入“package:path/path.dart”作为路径;
将“package:http/http.dart”导入为http;
变量图像=[
"https://c4.staticflickr.com/4/3880/15283361621_bc72a1fb29_z.jpg",
"https://c2.staticflickr.com/4/3923/15101476099_6e1087b76c_h.jpg",
"https://c2.staticflickr.com/4/3899/15288834802_073d2af478_z.jpg",
"https://c4.staticflickr.com/4/3880/15283361621_bc72a1fb29_z.jpg",
"https://c2.staticflickr.com/6/5575/15101869429_fa44a80e87_z.jpg",
"https://c1.staticflickr.com/3/2941/15100232360_03f3631c44_z.jpg",
"https://c1.staticflickr.com/3/2941/15269480156_a28e1c0dbb_b.jpg",
"https://c2.staticflickr.com/4/3907/15103503127_195ffcd5c0_z.jpg",
"https://c2.staticflickr.com/6/5595/15265903986_a3210505f4_c.jpg",
"https://c2.staticflickr.com/6/5567/15100857617_9926f2a189_z.jpg",
"https://c1.staticflickr.com/3/2941/15100542247_6e9c3f13ae_z.jpg",
"https://c2.staticflickr.com/4/3852/15099895539_cf43a904a5_z.jpg"
];
main(){
var期货=[];
images.forEach((url){
futures.add(新的http.Request('GET',Uri.parse(url))
.send()。然后((响应){
var f=新的io.File(path.basename(url));
var sink=f.openWrite();
sink.addStream(response.stream)
.然后(()=>sink.close());
}));
});
async.Future.wait(futures)//等待所有映像下载完成
。然后((u)=>打印('done');
}

谢谢。我自己也在研究Streams选项,但我自己也很困惑。我将尝试@DannyTuppeny解决方案,并按照您的建议增加堆大小。所有的下载都是同时进行的,这很可能就是问题所在。非常感谢。我将尝试重构我的代码以尝试您的解决方案。迫不及待地想听到您的反馈,如果这样可以解决内存问题而不增加堆。这对于解决我的内存问题非常有效。我可能想重新访问以支持同时下载多个文件。谢谢我学到了一些新东西。
dart --old_gen_heap_size=1024 somefile.dart 
export DART_VM_OPTIONS="--old_gen_heap_size=1024"