簡體   English   中英

如何更改此代碼以下載大於2GB的文件?

[英]How to change this code to download file bigger than 2GB?

我正在使用此代碼,適用於較小的文件,但無法下載文件大小超過2GB的文件。 我也嘗試過使用webclient ,但是它不適合我的代碼或無法正常工作,因為此代碼可以正常工作,只是試圖弄清楚如何使用此客戶端下載2GB文件。 謝謝

System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url_);
//request.Proxy = WebRequest.GetSystemWebProxy();
System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
ServicePoint sp = request.ServicePoint;
sp.ConnectionLimit = MAX_THREADS;
response.Close();
// gets the size of the file in bytes
Int64 iSize = response.ContentLength;
// keeps track of the total bytes downloaded so we can update the progress bar
Int64 iRunningByteTotal = 0;
UpdateStatus("File OK", count);
// use the webclient object to download the file
using (System.Net.WebClient client = new System.Net.WebClient())
{
    // open the file at the remote URL for reading
    using (System.IO.Stream streamRemote = client.OpenRead(new Uri(VideoUrl)))
    {
        // using the FileStream object, we can write the downloaded bytes to the file system
        using (Stream streamLocal = new FileStream(sFilePathToWriteFileTo, FileMode.Create, FileAccess.Write, FileShare.None))
        {
            // loop the stream and get the file into the byte buffer
            int iByteSize = 0;
            byte[] byteBuffer = new byte[iSize];<---------throws error here
            while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
            {
                if (isCanceled == true) return;
                if (manualResetEvent.WaitOne(0, false)) return;
                // write the bytes to the file system at the file path specified
                streamLocal.Write(byteBuffer, 0, iByteSize);
                iRunningByteTotal += iByteSize;

                // calculate the progress out of a base "100"
                double dIndex = (double)(iRunningByteTotal);
                double dTotal = (double)byteBuffer.Length;
                double dProgressPercentage = (dIndex / dTotal);
                int iProgressPercentage = (int)(dProgressPercentage * 100);
                UpdateProgress((int)iProgressPercentage, count);
            }

            // clean up the file stream
            streamLocal.Close();
        }
        // close the connection to the remote server
        streamRemote.Close();
    }
} 

錯誤

例外:

System.OverflowException was caught
  HResult=-2146233066
  Message=Arithmetic operation resulted in an overflow.
  Source=Downloader
  StackTrace:
       at MetroFramework.Demo.frmMain.FileDownloader(Object state) in frmMain.cs:line 595--->byte[] byteBuffer = new byte[iSize];
  InnerException: 

乍一看,您似乎已經正確地完成了所有操作:

  • 您已經分配了一個緩沖區
  • 您已經創建了一個填充緩沖區的循環
  • 然后,在迭代下一個緩沖區之前,將緩沖區刷新到文件
  • 您還包括了運行總計和進度更新

一切...保存一件事:

byte[] byteBuffer = new byte[iSize];

這會將緩沖區分配為要下載的文件的大小。 換句話說,如果文件的大小為1GiB,則分配1GiB的緩沖區,然后嘗試在一個調用中填充整個緩沖區。 這種填充可能返回較少的字節,但是您仍然分配了整個緩沖區。 請注意,.NET中單個數組的最大長度是一個32位數字,這意味着即使您將程序重新編譯為64位並且實際上有足夠的可用內存,對於大於2GiB的文件,它仍然會失敗。

這樣做:

byte[] byteBuffer = new byte[65536];

使用64KiB緩沖區或其他一些合理的緩沖區大小。

除了@Lasse的答案解決的緩沖區問題之外,實際的問題還在於您正在重新發明輪子。

使用WebClient.DownloadFile()並訂閱DownloadProgressChanged事件:

using (System.Net.WebClient client = new System.Net.WebClient())
{
    client.DownloadProgressChanged += WebClient_DownloadProgressChanged;

    client.DownloadFile(sourceUrl, targetFile);

    client.DownloadProgressChanged -= WebClient_DownloadProgressChanged;
}

private void WebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    // e.BytesReceived, 
    // e.TotalBytesToReceive,
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM