如何更改此代码以下载大于2GB的文件? [英] How to change this code to download file bigger than 2GB?

查看:80
本文介绍了如何更改此代码以下载大于2GB的文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用此代码,它适用于较小的文件,但无法下载文件大小超过2GB的文件。
我也尝试使用



异常:

  System.OverflowException被捕获
HResult = -2146233066
Message =算术运算导致溢出。
Source =下载程序
StackTrace:在MetroFramework.Demo.frmMain.FileDownloader(对象状态)中的
(在frmMain.cs中):线595 ---> byte [] byteBuffer = new byte [iSize ];
InnerException:


解决方案

您似乎已经完成了乍看之下一切正确:




  • 您已分配了缓冲区

  • 您已创建了一个填充缓冲区的循环

  • 然后在迭代下一个缓冲区之前,将缓冲区刷新到文件

  • 您还包括了运行总计和进度更新



一切...保存一件事:

  byte [] byteBuffer =新的byte [iSize]; 

这会将缓冲区分配为要下载文件的大小。换句话说,如果文件的大小为1GiB,则分配一个1 GiB的缓冲区,然后尝试在一个调用中填充整个缓冲区。这种填充可能会返回较少的字节,但是您仍然分配了整个缓冲区。请注意,.NET中单个数组的最大长度为32位数字,这意味着即使您重新编译程序为64位并且实际上具有足够的可用内存,对于大于2GiB的文件,它仍然会失败。



这样做:

  byte [] byteBuffer = new byte [65536]; 

使用64KiB缓冲区或其他一些合理的缓冲区大小。


I'm using this code it works good for smaller files but fails to download files with filesize over 2GB. I have tried to use webclient as well but it does not suit my code well or not working as this code works just trying to figure out how to download 2GB files with this one. Thanks

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();
    }
} 

Exception:

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: 

解决方案

You seem to have done everything correctly at first glance:

  • You've allocated a buffer
  • You've created a loop that fills the buffer
  • It then flushes the buffer to the file, before it iterates for the next buffer
  • You've also included running totals and progress updates

Everything... save one thing:

byte[] byteBuffer = new byte[iSize];

This allocates the buffer to be the size of the file to download. In other words, if the file is 1GiB in size, you allocate a 1 GiB buffer, and then you try to fill the whole buffer in one call. This filling may return fewer bytes but you've still allocated the whole buffer. Note that the maximum length of a single array in .NET is a 32-bit number which means that even if you recompile your program for 64bit and actually have enough memory available, it will still fail for files bigger than 2GiB.

So do this:

byte[] byteBuffer = new byte[65536];

Use a 64KiB buffer or some other sane buffer size.

这篇关于如何更改此代码以下载大于2GB的文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆