我使用此代码适用于较小的文件,但无法下载文件大小超过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:
答案 0 :(得分:2)
乍一看,你似乎完成了所有事情:
一切......保存一件事:
byte[] byteBuffer = new byte[iSize];
这会将缓冲区分配为要下载的文件的大小。换句话说,如果文件大小为1GiB,则分配1 GiB缓冲区,然后尝试在一次调用中填充整个缓冲区。这种填充可能返回更少的字节,但您仍然分配了整个缓冲区。请注意,.NET中单个数组的最大长度是32位数,这意味着即使您重新编译64位程序并且实际上有足够的可用内存,对于大于2GiB的文件,它仍然会失败。
这样做:
byte[] byteBuffer = new byte[65536];
使用64KiB缓冲区或其他一些合理的缓冲区大小。
答案 1 :(得分:2)
除了由@Lasse's answer修复的缓冲问题外,实际问题是您正在重新发明轮子。
使用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,
}