C# 文件未完全下载

C# 文件未完全下载,c#,stream,download,C#,Stream,Download,这是我从服务器下载ZIP文件的C代码。当我下载时,我没有收到文件,但它是部分下载的 public static void Download(String strURLFileandPath, String strFileSaveFileandPath) { HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(strURLFileandPath); HttpWebResponse ws = (HttpWebResponse)w

这是我从服务器下载ZIP文件的C代码。当我下载时,我没有收到文件,但它是部分下载的

public static void Download(String strURLFileandPath, String strFileSaveFileandPath)
{
    HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(strURLFileandPath);
    HttpWebResponse ws = (HttpWebResponse)wr.GetResponse();
    Stream str = ws.GetResponseStream();
    byte[] inBuf = new byte[100000];
    int bytesToRead = (int)inBuf.Length;
    int bytesRead = 0;
    while (bytesToRead > 0)
    {
        int n = str.Read(inBuf, bytesRead, bytesToRead);
        if (n == 0)
            break;
        bytesRead += n;
        bytesToRead -= n;
    }
    try
    {

        FileStream fstr = new FileStream(strFileSaveFileandPath, FileMode.OpenOrCreate, FileAccess.Write);
        fstr.Write(inBuf, 0, bytesRead);
        str.Close();
        fstr.Close();
    }
    catch (Exception e) {
        MessageBox.Show(e.Message);
    }
}
我想问题发生在这里

byte[] inBuf = new byte[100000];
当我增加
byte[]inBuf=新字节[100000]的值时
to
byte[]inBuf=新字节[10000000]

文件正在下载中

但我的问题是,如果我下载的文件大于50MB(例如:200MB)

这种方法不好


有人能告诉我如何解决这个问题吗?

边读边写。这样,您就不必在写入或完成下载之前将所有字节都保存在内存中

FileStream fstr = new FileStream(strFileSaveFileandPath, FileMode.OpenOrCreate, FileAccess.Write);
int bytesRead;
do
{
    bytesRead = str.Read(inBuf, 0, bytesToRead);
    fstr.Write(inBuf, 0, bytesRead);
}while (bytesToRead > 0);

str.Close();
fstr.Close();

您可以使用该方法直接从一个流复制到另一个流

或者更简单:使用类及其
DownloadFile
方法下载文件。此解决方案将取代您的完整方法:

var client = new WebClient();
client.DownloadFile(strURLFileandPath, strFileSaveFileandPath);

正如fero建议的那样,最好使用
Stream.CopyTo()

但是,如果您决定以手动方式将流复制到流(或者将来需要知道如何使用流),则永远不要手动指定缓冲区大小。您通常希望使用无重叠的最大缓冲区大小,以避免过多的内存消耗。对于ResponseStream,您可以为streamreader获取
ContentLength

 HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(strURLFileandPath);
 HttpWebResponse ws = (HttpWebResponse)wr.GetResponse();
 Stream str = ws.GetResponseStream();
 byte[] inBuf = new byte[str.ContentLength];
 int bytesToRead = (int)inBuf.Length;

还要记住和
Flush()
您的输出

您的键盘似乎有相同的问题。:)您的文件大小的标题中没有响应吗downloading@MikhailKozhevnikov我编辑这篇文章是为了反思和澄清,这不是最好的解决方案,只是对他的问题的一个回答。最好的解决方案是copyto方法,避免手动迭代流。感谢重播,但为什么表单没有响应?这是因为下载与UI在同一线程中执行。在下载文件时,用户界面无法处理任何消息。您应该使用该方法并将事件处理程序附加到
DownloadFileCompleted
事件,以便知道下载何时完成。请注意,下载方法调用将立即返回。任何需要完整本地文件的代码都必须放在事件处理程序中!谢谢你。我通过后台工作人员解决了这个问题,我希望为此设置一个进度条。网络客户端是否有任何下载进度事件?如果没有,如何设置进度条?为此,您必须使用
WebRequest
切换回解决方案。您也不能使用
CopyTo
。努内斯帕斯卡尔的答案更适合这里
bytesToRead
是缓冲区大小。在每个循环中,最多从请求中读取
bytesToRead
字节并写入文件。之后,您可以通过
bytesRead
增加进度计数
inBuf
必须定义为
byte[bytesToRead]
。然后将整个代码放在后台工作程序中。但是请记住,从另一个线程更新UI是相当棘手的(这在stackoverflow上已经讨论了很多)。