PC Review


Reply
Thread Tools Rate Thread

Corrupt PDF files When File is written to the response.

 
 
eventuranza@gmail.com
Guest
Posts: n/a
 
      22nd Aug 2006
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[i]);
Response.AddHeader(extraHeaders.GetKey(i),
extraHeaders[i]);
}
}

// 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.

 
Reply With Quote
 
 
 
 
Patrice
Guest
Posts: n/a
 
      22nd Aug 2006
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

<(E-Mail Removed)> a écrit dans le message de news:
(E-Mail Removed)...
> 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[i]);
> Response.AddHeader(extraHeaders.GetKey(i),
> extraHeaders[i]);
> }
> }
>
> // 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.
>



 
Reply With Quote
 
Tim_Mac
Guest
Posts: n/a
 
      22nd Aug 2006
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

<(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> 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[i]);
> Response.AddHeader(extraHeaders.GetKey(i),
> extraHeaders[i]);
> }
> }
>
> // 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.
>



 
Reply With Quote
 
=?Utf-8?B?UGV0ZXIgQnJvbWJlcmcgW0MjIE1WUF0=?=
Guest
Posts: n/a
 
      22nd Aug 2006
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




"(E-Mail Removed)" 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[i]);
> Response.AddHeader(extraHeaders.GetKey(i),
> extraHeaders[i]);
> }
> }
>
> // 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.
>
>

 
Reply With Quote
 
eventuranza@gmail.com
Guest
Posts: n/a
 
      23rd Aug 2006
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
>
> <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
> > 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[i]);
> > Response.AddHeader(extraHeaders.GetKey(i),
> > extraHeaders[i]);
> > }
> > }
> >
> > // 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.
> >


 
Reply With Quote
 
Damien
Guest
Posts: n/a
 
      23rd Aug 2006
(E-Mail Removed) 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

 
Reply With Quote
 
Tim_Mac
Guest
Posts: n/a
 
      23rd Aug 2006
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


 
Reply With Quote
 
lmcpferreira@gmail.com
Guest
Posts: n/a
 
      30th Aug 2006
Oh thankyou thankyou thankyou

.... same problem!...

 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Files being written to Response.OutputStream hang 25% of the time Chris Ashley Microsoft ASP .NET 0 5th Dec 2007 09:26 PM
Files being written to Response.OutputStream hang 25% of the time Chris Ashley Microsoft ASP .NET 0 5th Dec 2007 09:26 PM
What do FTP servers do when file send fails durring a file upload? Are partial files ever written? does ftp protocol cover this? Daniel Microsoft Windows 2000 Networking 0 30th Aug 2006 12:12 AM
What do FTP servers do when file send fails durring a file upload? Are partial files ever written? does ftp protocol cover this? Daniel Microsoft Dot NET 0 30th Aug 2006 12:12 AM
Why is my XML file being written corrupt? darrel Microsoft ASP .NET 3 6th Apr 2006 01:04 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 11:42 PM.