質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.51%

  • C#

    9062questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

巨大なファイルを非同期ダウンロードする処理について

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 123

kyosin

score 3

いつもお世話になっております。

現在c# にて8.1ギガのZipファイルをダウンロードしてみようと、以下のソースのような処理を書いて試しています。
現在発生している問題点は、ファイルが5.3ギガバイトを超えた時点で、「WebClientに例外的なエラーが発生しました」と
表示されて、完全なダウンロードが出来ない状態となっています。
4回ほど試しましたが、同じ5.3ギガバイト付近(正確には5381421398、5381319801、5381715394、5381385284)で
ダウンロードが中断されてしまいます。
timeoutが問題かと思い、20分に伸ばしてみましたが、5.3ギガバイトダウンロードした時点で、
それ以上ダウンロードされず、タイムアウトの時間を超えてから「WebClientに例外的なエラーが発生しました」と
メッセージが出るようになっています。

現状のソースコードでどこを変更することにより、8.1ギガのZIPファイルをダウンロードすることが
可能となるでしょうか?
また今利用しているWebClient自体、使用することをお勧めされていないようで
「非同期で、ダウンロードの進捗が目に見える、大容量ファイルのダウンロードも出来る」
の条件を満たした方法があるのでしょうか?

よろしくお願いいたします。

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Net;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //ダウンロード中のフラグ
        private bool onDownloading = false;

        //ダウンロード用のWebClient
        private MyWebClient wc = null;

    //処理時間計測用
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();

        //ダウンロードの進歩イベント
        private void wc_DownloadProgressChanged(Object sender, DownloadProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }

        //完了時のイベント
        private void wc_DownloadFileCompleted(Object sender, AsyncCompletedEventArgs e)
        {
            if ((e.Error != null) && (!e.Cancelled))
            {
                // 計測停止
                sw.Stop();
                TimeSpan ts = sw.Elapsed;

                MessageBox.Show("処理時間" + ts.ToString() + "ダウンロード中にエラーが発生しました。内容:" + e.Error.Message, "エラー",
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else if (e.Cancelled)
            {
                // 計測停止
                sw.Stop();
                TimeSpan ts = sw.Elapsed;

                MessageBox.Show("処理時間" + ts.ToString() + "ダウンロードがキャンセルされました。", "完了", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                // 計測停止
                sw.Stop();
                TimeSpan ts = sw.Elapsed;

                MessageBox.Show("処理時間" + ts.ToString() + "データのダウンロードが完了しました。", "完了", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            onDownloading = false;
        }

     //ダウンロードボタンクリック
        private void button1_Click(object sender, EventArgs e)
        {
            // 計測開始
            sw.Start();

            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            //8G.zipファイルをダウンロードする
            Uri uri = new Uri("8g.zip");

            if (wc == null)
            {
                wc = new MyWebClient();

                //webClientに進行状況、完了時のイベントハンドラを追加
                wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
                wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
            }

            //ダウンロード開始
            wc.DownloadFileAsync(uri, "output.zip");
            onDownloading = true;
        }

        //キャンセルボタンクリック
        private void button2_Click(object sender, EventArgs e)
        {
            //ダウンロード中なら、ダウンロードをキャンセルする
            if (onDownloading)
            {
                if (wc != null)
                {
                    wc.CancelAsync();
                }
            }
        }
    }

    //タイムアウト時間を延ばすためクラス作成
    public class MyWebClient : System.Net.WebClient
    {
        public int Timeout { get; set; } = 120 * 1000;

        protected override WebRequest GetWebRequest(Uri address)
        {
            var w = base.GetWebRequest(address);
            w.Timeout = Timeout;
            return w;
        }
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mts10806

    2019/05/15 15:55

    メモリの問題ではないでしょうか。
    逐一、使用メモリをチェックしてみては?

    キャンセル

  • mts10806

    2019/05/15 15:55

    回答かどうかというと完全に仮説なので「確認依頼」としてこちらに書きました。

    キャンセル

  • kyosin

    2019/05/15 16:17

    タスクマネージャー上にあるEXEのメモリの増減を見るで間違いないでしょうか?
    リリースしたEXEより試しますと起動時は4メガ、実行中は10~11メガと大きくなっていない状態でした。

    キャンセル

回答 1

checkベストアンサー

+4

サーバー側とクライアント側のどこに原因があるのかを調べるのは面倒です。どのみちそんな大きなファイルを一度にダウンロードしようというのが間違っているので、小さく分割してダウンロードしてください。そうすれば失敗したところからやり直すことができます。

参考
https://www.atmarkit.co.jp/fdotnet/dotnettips/710resumedown/resumedown.html

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/15 16:56

    ご教授いただき、ありがとうございます。

    URLを参照しました。
    「HttpWebRequestクラスのAddRangeメソッドではダウンロード開始位置だけでなく、開始位置と終了位置を指定することもできる」
    小さく分割をする場合、具体的にどのぐらいのサイズまで分割した方がよろしいのでしょうか?
    (サーバー、クライアント側の問題特定も理解できます。
    例えばZuishin様がこの問題を解決するに、まずはどのぐらいの容量分割から試してみるのでしょうか?)

    (※こちらは疑問に思っている内容です、もしお答えいただけるならお願いいたします。
    元々ブラウザ(Vivaldi)から直接、この8.1ギガのZIPファイルのダウンロードが
    出来ていた為、同じような考えでデータをダウンロード出来るのではと思っていました。
    Visualstudioのインストーラーでも、大容量のデータをダウンロードかつインストールしていたので、
    同じような方法でも問題ないのかと思い、このようなプログラムとデータを用意して試していました。
    ①サーバー、クライアント側の問題の特定が大変である事
    ②大容量のファイルのダウンロードはそう単純にプログラムでは解決しない(難易度が高い)
    ①②の点から、プログラムとしては安全策を取り、細かくダウンロードするが正解なのでしょうか?)

    キャンセル

  • 2019/05/15 17:01

    ブラウザからダウンロードできていたのは、おそらくブラウザが自動的に分割ダウンロードしていたからでしょう。

    分割する大きさは適当に決めてください。
    あまり小さくしすぎるとサーバーの負荷が高くなるので、失敗してもうんざりしない程度の大きさにまとめたらいいと思います。

    キャンセル

  • 2019/05/15 17:04

    わかりました、500メガぐらいの分割で
    ファイルのダウンロードを試そうと思います。

    ありがとうございました!

    キャンセル

同じタグがついた質問を見る

  • C#

    9062questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。