Corrupt PDF files When File is written to the response.

Discussion in 'ASP .Net' started by eventuranza@gmail.com, Aug 22, 2006.

  1. Guest

    For my application, there users can upload and download files to the a
    webserver. Straightforward enough. However, when they upload a PDF
    file then try to download it, the file seems to be corrupted. The had
    not been a problem before but it seems to have been introduced when I
    refactored the writing to the response to a buffered version to prevent
    potential OutOfMemoryExceptions (you wouldn't believe the size of some
    of these files...).

    Here's the code (pretty much jacked from a Microsoft knowledge base
    article):

    private void WriteToResponse(string filepath, string contentType,
    NameValueCollection extraHeaders)
    {
    Stream iStream = null;

    // Buffer to read 10K bytes in chunk:
    byte[] buffer = new Byte[10000];

    // Length of the file:
    int length;

    // Total bytes to read:
    long dataToRead;

    // Identify the file name.
    string filename = Path.GetFileName(filepath);

    try
    {
    // Open the file.
    iStream = new FileStream(filepath, FileMode.Open,
    FileAccess.Read, FileShare.Read);


    // Total bytes to read:
    dataToRead = iStream.Length;

    Response.ContentType = contentType;
    if(extraHeaders != null)
    {
    for (int i = 0; i < extraHeaders.Count; i++)
    {
    Trace.Write("adding Key value: " +
    extraHeaders.GetKey(i)
    + ". Adding value: " +
    extraHeaders);
    Response.AddHeader(extraHeaders.GetKey(i),
    extraHeaders);
    }
    }

    // Read the bytes.
    while (dataToRead > 0)
    {
    // Verify that the client is connected.
    if (Response.IsClientConnected)
    {
    // Read the data in buffer.
    length = iStream.Read(buffer, 0, 10000);

    // Write the data to the current output stream.
    Response.OutputStream.Write(buffer, 0, length);

    // Flush the data to the HTML output.
    Response.Flush();

    buffer = new Byte[10000];
    dataToRead = dataToRead - length;
    }
    else
    {
    //prevent infinite loop if user disconnects
    dataToRead = -1;
    }
    }
    }
    catch(IOException ioEx)
    {
    errorRow.Visible = true;
    lblErrorMsg.Text = ioEx.Message;
    log.Error(ioEx.ToString());
    }
    catch (Exception ex)
    {
    errorRow.Visible = true;
    // Trap the error, if any.
    log.Error(ex.ToString());
    }
    finally
    {
    if (iStream != null)
    {
    //Close the file.
    iStream.Close();
    }
    }
    }

    Thanks in advance for any help.
    , Aug 22, 2006
    #1
    1. Advertising

  2. Patrice Guest

    Trace not enabled ? All HTML stripped ? (using Response.Clear allows to make
    sure you won't have a character coming from your APSX markup).

    IMO The easiest path is to save the file (possibly using a content
    disposition header) so that you can check the length. If not the length you
    can do a file comparison to see where the file is corrupted.

    --
    Patrice

    <> a écrit dans le message de news:
    ...
    > For my application, there users can upload and download files to the a
    > webserver. Straightforward enough. However, when they upload a PDF
    > file then try to download it, the file seems to be corrupted. The had
    > not been a problem before but it seems to have been introduced when I
    > refactored the writing to the response to a buffered version to prevent
    > potential OutOfMemoryExceptions (you wouldn't believe the size of some
    > of these files...).
    >
    > Here's the code (pretty much jacked from a Microsoft knowledge base
    > article):
    >
    > private void WriteToResponse(string filepath, string contentType,
    > NameValueCollection extraHeaders)
    > {
    > Stream iStream = null;
    >
    > // Buffer to read 10K bytes in chunk:
    > byte[] buffer = new Byte[10000];
    >
    > // Length of the file:
    > int length;
    >
    > // Total bytes to read:
    > long dataToRead;
    >
    > // Identify the file name.
    > string filename = Path.GetFileName(filepath);
    >
    > try
    > {
    > // Open the file.
    > iStream = new FileStream(filepath, FileMode.Open,
    > FileAccess.Read, FileShare.Read);
    >
    >
    > // Total bytes to read:
    > dataToRead = iStream.Length;
    >
    > Response.ContentType = contentType;
    > if(extraHeaders != null)
    > {
    > for (int i = 0; i < extraHeaders.Count; i++)
    > {
    > Trace.Write("adding Key value: " +
    > extraHeaders.GetKey(i)
    > + ". Adding value: " +
    > extraHeaders);
    > Response.AddHeader(extraHeaders.GetKey(i),
    > extraHeaders);
    > }
    > }
    >
    > // Read the bytes.
    > while (dataToRead > 0)
    > {
    > // Verify that the client is connected.
    > if (Response.IsClientConnected)
    > {
    > // Read the data in buffer.
    > length = iStream.Read(buffer, 0, 10000);
    >
    > // Write the data to the current output stream.
    > Response.OutputStream.Write(buffer, 0, length);
    >
    > // Flush the data to the HTML output.
    > Response.Flush();
    >
    > buffer = new Byte[10000];
    > dataToRead = dataToRead - length;
    > }
    > else
    > {
    > //prevent infinite loop if user disconnects
    > dataToRead = -1;
    > }
    > }
    > }
    > catch(IOException ioEx)
    > {
    > errorRow.Visible = true;
    > lblErrorMsg.Text = ioEx.Message;
    > log.Error(ioEx.ToString());
    > }
    > catch (Exception ex)
    > {
    > errorRow.Visible = true;
    > // Trap the error, if any.
    > log.Error(ex.ToString());
    > }
    > finally
    > {
    > if (iStream != null)
    > {
    > //Close the file.
    > iStream.Close();
    > }
    > }
    > }
    >
    > Thanks in advance for any help.
    >
    Patrice, Aug 22, 2006
    #2
    1. Advertising

  3. Tim_Mac Guest

    hi,
    did you try using Response.BufferOutput = true;
    i thought that was supposed to buffer the output to the client in smaller
    chunks.
    ..Net 2.0 has a method called Response.TransmitFile() which according to the
    docs says that it sends a file straight to the client without loading the
    contents into memory. it must do a direct stream transfer from the file to
    the http response.

    the thought of doing tracing in the middle of a binary write makes me a bit
    suspicious, surely this would corrupt the download? not sure though if the
    trace strings actually get written out with the response.

    thanks
    tim

    <> wrote in message
    news:...
    > For my application, there users can upload and download files to the a
    > webserver. Straightforward enough. However, when they upload a PDF
    > file then try to download it, the file seems to be corrupted. The had
    > not been a problem before but it seems to have been introduced when I
    > refactored the writing to the response to a buffered version to prevent
    > potential OutOfMemoryExceptions (you wouldn't believe the size of some
    > of these files...).
    >
    > Here's the code (pretty much jacked from a Microsoft knowledge base
    > article):
    >
    > private void WriteToResponse(string filepath, string contentType,
    > NameValueCollection extraHeaders)
    > {
    > Stream iStream = null;
    >
    > // Buffer to read 10K bytes in chunk:
    > byte[] buffer = new Byte[10000];
    >
    > // Length of the file:
    > int length;
    >
    > // Total bytes to read:
    > long dataToRead;
    >
    > // Identify the file name.
    > string filename = Path.GetFileName(filepath);
    >
    > try
    > {
    > // Open the file.
    > iStream = new FileStream(filepath, FileMode.Open,
    > FileAccess.Read, FileShare.Read);
    >
    >
    > // Total bytes to read:
    > dataToRead = iStream.Length;
    >
    > Response.ContentType = contentType;
    > if(extraHeaders != null)
    > {
    > for (int i = 0; i < extraHeaders.Count; i++)
    > {
    > Trace.Write("adding Key value: " +
    > extraHeaders.GetKey(i)
    > + ". Adding value: " +
    > extraHeaders);
    > Response.AddHeader(extraHeaders.GetKey(i),
    > extraHeaders);
    > }
    > }
    >
    > // Read the bytes.
    > while (dataToRead > 0)
    > {
    > // Verify that the client is connected.
    > if (Response.IsClientConnected)
    > {
    > // Read the data in buffer.
    > length = iStream.Read(buffer, 0, 10000);
    >
    > // Write the data to the current output stream.
    > Response.OutputStream.Write(buffer, 0, length);
    >
    > // Flush the data to the HTML output.
    > Response.Flush();
    >
    > buffer = new Byte[10000];
    > dataToRead = dataToRead - length;
    > }
    > else
    > {
    > //prevent infinite loop if user disconnects
    > dataToRead = -1;
    > }
    > }
    > }
    > catch(IOException ioEx)
    > {
    > errorRow.Visible = true;
    > lblErrorMsg.Text = ioEx.Message;
    > log.Error(ioEx.ToString());
    > }
    > catch (Exception ex)
    > {
    > errorRow.Visible = true;
    > // Trap the error, if any.
    > log.Error(ex.ToString());
    > }
    > finally
    > {
    > if (iStream != null)
    > {
    > //Close the file.
    > iStream.Close();
    > }
    > }
    > }
    >
    > Thanks in advance for any help.
    >
    Tim_Mac, Aug 22, 2006
    #3
  4. Try using the (new in ASP.NET 2.0) Response.TransmitFile method.
    Peter

    --
    Co-founder, Eggheadcafe.com developer portal:
    http://www.eggheadcafe.com
    UnBlog:
    http://petesbloggerama.blogspot.com




    "" wrote:

    > For my application, there users can upload and download files to the a
    > webserver. Straightforward enough. However, when they upload a PDF
    > file then try to download it, the file seems to be corrupted. The had
    > not been a problem before but it seems to have been introduced when I
    > refactored the writing to the response to a buffered version to prevent
    > potential OutOfMemoryExceptions (you wouldn't believe the size of some
    > of these files...).
    >
    > Here's the code (pretty much jacked from a Microsoft knowledge base
    > article):
    >
    > private void WriteToResponse(string filepath, string contentType,
    > NameValueCollection extraHeaders)
    > {
    > Stream iStream = null;
    >
    > // Buffer to read 10K bytes in chunk:
    > byte[] buffer = new Byte[10000];
    >
    > // Length of the file:
    > int length;
    >
    > // Total bytes to read:
    > long dataToRead;
    >
    > // Identify the file name.
    > string filename = Path.GetFileName(filepath);
    >
    > try
    > {
    > // Open the file.
    > iStream = new FileStream(filepath, FileMode.Open,
    > FileAccess.Read, FileShare.Read);
    >
    >
    > // Total bytes to read:
    > dataToRead = iStream.Length;
    >
    > Response.ContentType = contentType;
    > if(extraHeaders != null)
    > {
    > for (int i = 0; i < extraHeaders.Count; i++)
    > {
    > Trace.Write("adding Key value: " +
    > extraHeaders.GetKey(i)
    > + ". Adding value: " +
    > extraHeaders);
    > Response.AddHeader(extraHeaders.GetKey(i),
    > extraHeaders);
    > }
    > }
    >
    > // Read the bytes.
    > while (dataToRead > 0)
    > {
    > // Verify that the client is connected.
    > if (Response.IsClientConnected)
    > {
    > // Read the data in buffer.
    > length = iStream.Read(buffer, 0, 10000);
    >
    > // Write the data to the current output stream.
    > Response.OutputStream.Write(buffer, 0, length);
    >
    > // Flush the data to the HTML output.
    > Response.Flush();
    >
    > buffer = new Byte[10000];
    > dataToRead = dataToRead - length;
    > }
    > else
    > {
    > //prevent infinite loop if user disconnects
    > dataToRead = -1;
    > }
    > }
    > }
    > catch(IOException ioEx)
    > {
    > errorRow.Visible = true;
    > lblErrorMsg.Text = ioEx.Message;
    > log.Error(ioEx.ToString());
    > }
    > catch (Exception ex)
    > {
    > errorRow.Visible = true;
    > // Trap the error, if any.
    > log.Error(ex.ToString());
    > }
    > finally
    > {
    > if (iStream != null)
    > {
    > //Close the file.
    > iStream.Close();
    > }
    > }
    > }
    >
    > Thanks in advance for any help.
    >
    >
    =?Utf-8?B?UGV0ZXIgQnJvbWJlcmcgW0MjIE1WUF0=?=, Aug 22, 2006
    #4
  5. Guest

    Thanks for all your input. What it turned to be was my neglecting to
    put in "Response.End()" at the end of this method. The files that were
    being downloaded actually had the emitted HTML response appended to the
    end of the file. It turns out that out of out of a whole cross section
    of files, ranging form movie files to Office and images, the PDF was
    most sensitive to this extra information after the EOF and was gettin
    gcorrupted.


    Tim_Mac wrote:
    > hi,
    > did you try using Response.BufferOutput = true;
    > i thought that was supposed to buffer the output to the client in smaller
    > chunks.
    > .Net 2.0 has a method called Response.TransmitFile() which according to the
    > docs says that it sends a file straight to the client without loading the
    > contents into memory. it must do a direct stream transfer from the file to
    > the http response.
    >
    > the thought of doing tracing in the middle of a binary write makes me a bit
    > suspicious, surely this would corrupt the download? not sure though if the
    > trace strings actually get written out with the response.
    >
    > thanks
    > tim
    >
    > <> wrote in message
    > news:...
    > > For my application, there users can upload and download files to the a
    > > webserver. Straightforward enough. However, when they upload a PDF
    > > file then try to download it, the file seems to be corrupted. The had
    > > not been a problem before but it seems to have been introduced when I
    > > refactored the writing to the response to a buffered version to prevent
    > > potential OutOfMemoryExceptions (you wouldn't believe the size of some
    > > of these files...).
    > >
    > > Here's the code (pretty much jacked from a Microsoft knowledge base
    > > article):
    > >
    > > private void WriteToResponse(string filepath, string contentType,
    > > NameValueCollection extraHeaders)
    > > {
    > > Stream iStream = null;
    > >
    > > // Buffer to read 10K bytes in chunk:
    > > byte[] buffer = new Byte[10000];
    > >
    > > // Length of the file:
    > > int length;
    > >
    > > // Total bytes to read:
    > > long dataToRead;
    > >
    > > // Identify the file name.
    > > string filename = Path.GetFileName(filepath);
    > >
    > > try
    > > {
    > > // Open the file.
    > > iStream = new FileStream(filepath, FileMode.Open,
    > > FileAccess.Read, FileShare.Read);
    > >
    > >
    > > // Total bytes to read:
    > > dataToRead = iStream.Length;
    > >
    > > Response.ContentType = contentType;
    > > if(extraHeaders != null)
    > > {
    > > for (int i = 0; i < extraHeaders.Count; i++)
    > > {
    > > Trace.Write("adding Key value: " +
    > > extraHeaders.GetKey(i)
    > > + ". Adding value: " +
    > > extraHeaders);
    > > Response.AddHeader(extraHeaders.GetKey(i),
    > > extraHeaders);
    > > }
    > > }
    > >
    > > // Read the bytes.
    > > while (dataToRead > 0)
    > > {
    > > // Verify that the client is connected.
    > > if (Response.IsClientConnected)
    > > {
    > > // Read the data in buffer.
    > > length = iStream.Read(buffer, 0, 10000);
    > >
    > > // Write the data to the current output stream.
    > > Response.OutputStream.Write(buffer, 0, length);
    > >
    > > // Flush the data to the HTML output.
    > > Response.Flush();
    > >
    > > buffer = new Byte[10000];
    > > dataToRead = dataToRead - length;
    > > }
    > > else
    > > {
    > > //prevent infinite loop if user disconnects
    > > dataToRead = -1;
    > > }
    > > }
    > > }
    > > catch(IOException ioEx)
    > > {
    > > errorRow.Visible = true;
    > > lblErrorMsg.Text = ioEx.Message;
    > > log.Error(ioEx.ToString());
    > > }
    > > catch (Exception ex)
    > > {
    > > errorRow.Visible = true;
    > > // Trap the error, if any.
    > > log.Error(ex.ToString());
    > > }
    > > finally
    > > {
    > > if (iStream != null)
    > > {
    > > //Close the file.
    > > iStream.Close();
    > > }
    > > }
    > > }
    > >
    > > Thanks in advance for any help.
    > >
    , Aug 23, 2006
    #5
  6. Damien Guest

    wrote:
    > Thanks for all your input. What it turned to be was my neglecting to
    > put in "Response.End()" at the end of this method. The files that were
    > being downloaded actually had the emitted HTML response appended to the
    > end of the file. It turns out that out of out of a whole cross section
    > of files, ranging form movie files to Office and images, the PDF was
    > most sensitive to this extra information after the EOF and was gettin
    > gcorrupted.
    >
    >

    Glad you sorted it, but can I just ask, why do you continually
    reallocate the buffer in your loop? Surely that would increase the
    memory pressure?

    Damien
    Damien, Aug 23, 2006
    #6
  7. Tim_Mac Guest

    hi,
    you may prefer to use Response.Close()
    in .net 1.1 i ran into ThreadAbortExceptions when using Response.End.
    changing this to Response.Close() solved the problem.

    tim
    Tim_Mac, Aug 23, 2006
    #7
  8. Guest

    Oh thankyou thankyou thankyou

    .... same problem!...
    , Aug 30, 2006
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jacky Kwok

    Re: Mail object and Corrupt PDF Files

    Jacky Kwok, Aug 27, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    1,825
    DataNumen
    Nov 18, 2006
  2. MSFT
    Replies:
    0
    Views:
    357
  3. darrel
    Replies:
    3
    Views:
    554
    Darrel
    Apr 6, 2006
  4. =?Utf-8?B?QmFkaXM=?=

    PDF File Corrupt

    =?Utf-8?B?QmFkaXM=?=, Jan 15, 2007, in forum: ASP .Net
    Replies:
    1
    Views:
    381
    Mark Fitzpatrick
    Jan 15, 2007
  5. iporter
    Replies:
    6
    Views:
    580
    Anthony Jones
    Mar 30, 2007
Loading...

Share This Page