Arun
Arun

Reputation: 685

File is not downloading completely

This is my C# code to download a ZIP file from my server. When I download I don't receive the file, but it is partially downloaded.

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

I thing the problem is happening here

byte[] inBuf = new byte[100000];

When I increase the value of byte[] inBuf = new byte[100000]; to byte[] inBuf = new byte[10000000];

The file is downloading perfectly.

But my problem is if I download files larger than 50 MB (eg.: 200 MB) .

This method is not good.

Can anyone tell me how can I fix this problem?

Upvotes: 2

Views: 1851

Answers (3)

fero
fero

Reputation: 6183

You could copy directly from stream to stream using the Stream.CopyTo() method.

Or even simpler: Use the WebClient class and its DownloadFile method to download the file. This solution would replace your complete method:

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

Upvotes: 3

nyxthulhu
nyxthulhu

Reputation: 9752

As fero suggested its best to use Stream.CopyTo()

However if your determined to do it the copy stream to stream manually way ( or need to know how to use streams in the future ) you should never manually specify the buffer size. You generally want to use the maximum size of buffer with no overlap to avoid excessive memory consumption, in the case of the ResponseSream you can get the ContentLength for your streamreader

 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;

Also remember and Flush() your output.

Upvotes: 0

nunespascal
nunespascal

Reputation: 17724

Write the file as you read it. That way, you won't have to keep all the bytes in memory before you write or finish downloading.

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

Upvotes: 0

Related Questions