RHPT
RHPT

Reputation: 2650

Downloading a PDF from the internet results in partial file

I am trying to download a pdf from Amazon S3 using the code below. However, the file only partially downloads and can't be opened. (The code is amalgam of other SO answers and random Google searching).

byte[] buffer = new byte[32768];
long byteCount;
string filename = "random.pdf";

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(<url-to-s3>);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream resStream = response.GetResponseStream();

while ((byteCount = resStream.Read(buffer, 0, buffer.Length)) > 0)
{
    if (Response.IsClientConnected)
    {
        Response.ContentType = "application/pdf";
        Response.AddHeader("Content-Disposition", "attachment;filename=" + filename);
        Response.OutputStream.Write(buffer, 0, buffer.Length);
        Response.Flush();
        Response.Close();
        Response.End();
    }
}

Upvotes: 0

Views: 1498

Answers (1)

lc.
lc.

Reputation: 116528

I'm assuming the file is bigger than 32k, in which case you're flushing and closing the response before all bytes are read. Additionally, you should be sending the client only the bytes read (denoted by byteCount) and not the entire buffer regardless. You also don't need to set the Response.ContentType and add duplicate headers for each buffering operation. Try:

Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment;filename=" + filename);

while ((byteCount = resStream.Read(buffer, 0, buffer.Length)) > 0)
{
    Response.OutputStream.Write(buffer, 0, byteCount);    
}

Response.Flush();
Response.Close();
Response.End();

I'm also assuming you're not getting an error per se - likely because Response.End() would disconnect the client so Response.IsClientConnected returns false.


That being said, you should be able to just use Stream.CopyTo to copy the streams without explicitly controlling the read-buffer-write operation yourself:

Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment;filename=" + filename);

reStream.CopyTo(Response.OutputStream);

Response.Flush();
Response.Close();
Response.End();

If you want to specify 32k buffers, just use the Stream.CopyTo(Stream, int) overload:

reStream.CopyTo(Response.OutputStream, 32768);

Upvotes: 1

Related Questions