并行下载大量文件的有效方法

2024-03-09

我正在尝试从互联网下载大量文件(图片)。我正在努力处理异步/并行,因为

a) 我不能说是否有文件。我刚刚收到一百万个链接,其中要么是一张图片(300kb 到 3MB),要么是 404 页面不存在。因此,为了避免下载 0 字节文件,我询问同一页面两次,一次是 404,另一次是图片。另一种方法是下载所有 0 字节文件,然后删除数百万个文件 - 这会让 Windows 10 一直停留在这个任务上,直到我重新启动。

b) 当(非常慢)下载正在进行时,每当我查看任何“成功下载的文件”时,它都是用 0 字节创建的,并且不包含图片。我需要更改什么才能在下载下一个文件之前真正下载该文件?

我该如何解决这两个问题?有没有更好的方法来下载数千或数百万个文件(不可能在服务器上压缩/创建 .zip)

           //loopResult = Parallel.ForEach(_downloadLinkList, new ParallelOptions { MaxDegreeOfParallelism = 10 }, DownloadFilesParallel);    
            private async void DownloadFilesParallel(string path)
            {
                string downloadToDirectory = ""; 
                string x = ""; //in case x fails, i get 404 from webserver and therefore no download is needed
                System.Threading.Interlocked.Increment(ref downloadCount);
                OnNewListEntry(downloadCount.ToString() + " / " + linkCount.ToString() + " heruntergeladen"); //tell my gui to update
                try
                {
                    using(WebClient webClient = new WebClient())
                    {
                        downloadToDirectory = Path.Combine(savePathLocalComputer, Path.GetFileName(path)); //path on local computer

                        webClient.Credentials = CredentialCache.DefaultNetworkCredentials;
                        x = await webClient.DownloadStringTaskAsync(new Uri(path)); //if this throws an exception, ignore this link
                        Directory.CreateDirectory(Path.GetDirectoryName(downloadToDirectory)); //if request is successfull, create -if needed- the folder on local pc
                        await webClient.DownloadFileTaskAsync(new Uri(path), @downloadToDirectory); //should download the file, release 1 parallel task to get the next file. instead there is a 0-byte file and the next one will be downloaded
                    }
                }
                catch(WebException wex)
                {
                }
                catch(Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }
                finally
                {
                    
                }
            }

//picture is sfw, link is nsfw enter image description here


这是使用的示例HttpClient https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netframework-4.8具有最大并发下载限制。

private static readonly HttpClient client = new HttpClient();

private async Task DownloadAndSaveFileAsync(string path, SemaphoreSlim semaphore, IProgress<int> status)
{
    try
    {
        status?.Report(semaphore.CurrentCount);
        using (HttpResponseMessage response = await client.GetAsync(path, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
        {
            if (response.IsSuccessStatusCode) // ignoring if not success
            {
                string filePath = Path.Combine(savePathLocalComputer, Path.GetFileName(path));
                string dir = Path.GetDirectoryName(filePath);
                if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
                using (Stream responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                using (FileStream fileStream = File.Create(filePath))
                {
                    await responseStream.CopyToAsync(fileStream).ConfigureAwait(false);
                }
            }
        }
    }
    finally
    {
        semaphore.Release();
    }
}

并发数

client.BaseAddress = "http://somesite";
int downloadCount = 0;
List<string> pathList = new List<string>();
// fill the list here

List<Task> tasks = new List<Task>();
int maxConcurrentTasks = Environment.ProcessorCount * 2; // 16 for me

IProgress<int> status = new Progress<int>(availableTasks =>
{
    downloadCount++;
    OnNewListEntry(downloadCount + " / " + pathList.Count + " heruntergeladen\r\nRunning " + (maxConcurrentTasks - availableTasks) + " downloads.");
});

using (SemaphoreSlim semaphore = new SemaphoreSlim(maxConcurrentTasks))
{
    foreach (string path in pathList)
    {
        await semaphore.WaitAsync();
        tasks.Add(DownloadAndSaveFileAsync(path, semaphore, status));
    }
    try
    {
        await Task.WhenAll(tasks);
    }
    catch (Exception ex)
    {
        // handle the Exception here
    }
}

Progress这里只是在 UI 线程上执行回调。因此Interlocked内部不需要,更新 UI 是安全的。

如果是.NET Framework(在.NET Core中没有效果但不需要)为了使其更快,您可以将此行添加到应用程序启动代码中

ServicePointManager.DefaultConnectionLimit = 10;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

并行下载大量文件的有效方法 的相关文章

随机推荐

  • 解封时出现属性错误:无法获取属性“位置”

    我正在为库存系统编写 Python CGI 脚本 需要通过存储pickle一个列表 称为locations 的对象 这是我正在使用的代码 try with open config autosave bin rb as dataFile lo
  • 整数分数约简算法

    这来源于最近完成的一次编程比赛 给你两个 10 5 整数的数组 范围在 1 10 7 含 内 int N 100000 int D 100000 想象有理数 X 是 N 的所有元素相乘并除以 D 的所有元素的结果 修改两个数组而不更改 X
  • Bootstrap 3 导航栏 - 无法正确折叠

    导航栏曾经正常工作 但我做了一些更改 它不再工作 当我将窗口缩小时 会显示切换方块 但是当我单击它时 什么也没有发生 Note 导航栏在全屏下工作正常 它只是在小窗口中 当我单击切换按钮时 下拉菜单不会出现 想知道是否有人知道如何解决它 这
  • 无法在 Eclipse 上调试基于 Android 库构建的 Android 本机代码

    我已经为此苦苦挣扎了三天 但无法完成 我有一个 android 项目 它链接到 eclipse 上的 android 库 其中包含本机代码 I saw 这个问题 https stackoverflow com questions 12638
  • pandas - 获取日期时间数据框中每天的第一个和最后一个值

    我有一个月的数据框 不包括周六和周日 每 1 分钟记录一次 v1 v2 2017 04 03 09 15 00 35 7 35 4 2017 04 03 09 16 00 28 7 28 5 2017 04 03 16 29 00 81 7
  • 处理表中的溢出

    如果我有一个像这样非常非常简单的例子的表 table table layout fixed width 300px td1 width 100px td2 width 200px 在我的其中之一 td2包含一个图像 可以说 300px in
  • C++ 删除静态数据

    如果我有一个类 其中包含分配在堆上且永不更改的私有静态数据 那么我应该什么时候 如果有的话 删除它 据我了解 类本身永远不会被构造 因为类不是 C 中的第一类对象 那么没有析构函数来删除其中的静态数据 我是 C 新手 如果我对 C 的理解有
  • 如何使用logstash插件-logstash-input-http

    我正在探索 Logstash 以接收 HTTP 上的输入 我已经使用以下方式安装了 http 插件 插件安装logstash input http 安装成功 然后我尝试使用以下命令运行logstash Logstash e 输入 http
  • R:Tibble 与 ggplot2(绘制图表)

    我正在尝试遵循 R 中的教程 https rviews rstudio com 2017 09 25 survival analysis with r https rviews rstudio com 2017 09 25 survival
  • 当用户调整 QMainWindow 大小时如何分配回调?

    我既无法在 QMainWindow 上找到类似教程的调整大小事件方案 也没有在 Qt 设计窗口的下拉菜单中看到任何用于添加调整大小事件的选项 我是 Qt 新手 我想为 QMainWindow 调整大小事件编写一个槽函数 有这样的活动吗 我怎
  • 在 Excel 中设置 csv 文件格式

    Win XP Excel 2007 我知道还有很多关于 csv 格式的其他帖子 但无法找到我需要的内容 我们的一些数据被另一家公司保存在异地 他们每天早上都会向我们发送包含前几天数据的 csv 文件 问题是这些数据来自可能具有下拉列表的网络
  • 使用sync_imports()在IPython.parallel引擎上导入自定义模块

    我一直在玩 IPython parallel 我想使用我自己的一些自定义模块 但无法按照上的说明进行操作烹饪书 http ipython org ipython doc stable parallel parallel multiengin
  • Nifty Modal - 如何在没有按钮的情况下触发模式

    这个脚本 http stuff wp dreams com modal 提供了很棒的模式转换 我想使用它们而不是标准的警报消息 现在脚本的演示展示了如何通过按 a 来触发它们
  • 如何从 R 读取换行符分隔的 JSON 文件?

    我有一个换行符分隔 即每个 JSON 对象仅限于文件中的 1 行 name json1 name json2 name json3 在Python中 我可以轻松地阅读它 如下所示 我必须使用编码encoding cp850 读取我的真实数据
  • IllegalStateException:数据库已关闭(使用 ViewPager)

    我对导致此错误的原因感到困惑 因为我已确保正确关闭数据库适配器 至少我认为是 以下是 LogCat 的说法 所有这些标签的标签都是 AndroidRuntime 致命异常 主要 java lang IllegalStateException
  • 从 ASP.NET Core Web API 将多 GB 文件流式传输到 AWS S3

    我希望通过 ASP NET Core Web API 在 AWS S3 存储桶中创建一个大型 多 GB 文件 该文件足够大 我不想加载Stream在将其上传到 AWS S3 之前先将其存储到内存中 Using PutObjectAsync
  • 如何拆分结果中尾随空字符串的字符串?

    我对 Scala 字符串分割行为有点困惑 因为它不能一致地工作 并且缺少一些列表元素 例如 如果我有一个包含 4 列和 1 个缺失元素的 CSV 字符串 elem1 elem2 elem 4 split List elem1 elem2 e
  • [Cucumber][JVM][Maven]测试无法通过 maven 从命令行运行

    我正在使用 java cucumber 和 Maven 运行测试 我正在使用 Eclipse IDE pom xml 也具有 Cucumber 依赖项 我以两种方式运行测试 从 Eclipse IDE 我将测试作为 Junit 测试运行 测
  • 如何防止未经授权的蜘蛛抓取

    我想防止从我们的网站之一自动抓取 html 同时不影响合法的蜘蛛抓取 googlebot 等 是否已经存在可以实现此目的的东西 我是否使用了正确的术语 编辑 我主要是为了防止人们恶意这样做 IE 他们不会遵守 robots txt EDIT
  • 并行下载大量文件的有效方法

    我正在尝试从互联网下载大量文件 图片 我正在努力处理异步 并行 因为 a 我不能说是否有文件 我刚刚收到一百万个链接 其中要么是一张图片 300kb 到 3MB 要么是 404 页面不存在 因此 为了避免下载 0 字节文件 我询问同一页面两