End of result from BinaryWrite Flush is missing - c#

I'm having some problems dealing with downloading a file from the server.
The problem is that the end of the downloaded file is missing.
I have found some indications of other people having similar problems, but nothing that helps me in my problem.
When debugging I have learned that the length of fileData is correct, and all data is present in the byte array when calling BinaryWrite.
That leaves the BinaryWrite, Flush or Close calls...
I have read about not using Response.End or Response.Close, for example here:
HttpResponse.End vs HttpResponse.Close vs HttpResponse.SuppressContent and it seems like a probable cause, but what should I use instead (have tried to remove Response.Close completely, but that result in too much data output)?
Someone knows what might cause this behaviour, and how to fix it?
EDIT: Just tried with Response.ContentType = "binary/octet-stream"; and it works like a charm!
What is the difference between text/plain and binary/octet-stream that may cause a behavior like this?
It even works without the Close call...
MORE EDIT: Seems like compression of Responses was activated on the server-side. Apparently there seems to be an issue with plain text streams when compression is active.
The code I have is:
private void DownloadFile(byte[] fileData, string fileName, string fileExtension)
{
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=" + fileName + fileExtension);
Response.AddHeader("Content-Length", fileData.Length.ToString(CultureInfo.InvariantCulture));
Response.ContentType = "text/plain";
Response.BinaryWrite(fileData);
Response.Flush();
Response.Close();
}

If compression is active on the server-side (IIS) it apparently causes trouble with text/plain streams.
For you with similar problems, try deactivating, it might help!
It surely did for me!

Related

HP Fortify Cross Site Scripting Issue on File BinaryWrite

I have the below code when scanned through HP Fortify, showed XSS issue on the following line : Response.BinaryWrite(buffer);
What can I do to fix the XSS issue pointed out by Fortify?
void ShowPDF(string infilepath)
{
WebClient client = new WebClient();
Byte[] buffer = client.DownloadData(infilepath);
Response.ContentType = "application/pdf";
Response.AddHeader("content-length", buffer.Length.ToString());
Response.AddHeader("content-disposition","attachment; filename=hearingprep.pdf");
Response.BinaryWrite(buffer);
}
Any help will be deeply appreciated.
What Fortify said is that you put untrusted content to the browser.
When you do BinaryWrite(buffer). The rule triggered from Fortify is probably because you use directly the buffer coming from DownloadData (who come from a untrusted source ).
So First, try to add a sanitizing capability to your code on the string infilepathand see what's happen.
After that, if you can add sanitizing to the Byte[] buffer, this should definitively solve the vulns spot by Fortify.
If you can not do the 2., you should be prepare to have really a XSS.
Raised the issue as false positive, with ensuring the incoming file locations as trusted location.

Thread was being aborted using TransmitFile

There are a ton of threads Stackoverflow about this error, but none of them seem to help me solve my problem.
I'm transferring a small Excel file from server to client. My code:
protected void SaveSpreadsheet(string filePath)
{
FileInfo myfile = new FileInfo(filePath);
if (myfile.Exists)
{
Response.ClearContent();
Response.AddHeader("Content-Disposition", "attachment; filename=" + myfile.Name);
Response.AddHeader("Content-Length", myfile.Length.ToString());
Response.ContentType = "xlsx";
Response.TransmitFile(myfile.FullName);
Response.End();
// Delete the file from the server
if (File.Exists(strSaveFilePath))
{
File.Delete(strSaveFilePath);
}
}
}
I'm getting the 'Thread was being aborted' error. I know from troubleshooting that the Response.End(); line is the problem.
A lot of the problems associated with this error are from people using Response.Redirect, but those solutions don't seem work for me. According to Microsoft, replacing that line with HttpContext.Current.ApplicationInstance.CompleteRequest was their solution, but that gives me another error.
Many of the solutions on this and other sites recommend moving this code outside my Try-Catch block. I tried that, but the last part of my code (deleting the file) does not work, so I know I'm still getting an error.
Can anyone help me solve this problem? Thanks.

ASP Force download txt file sending back source instead

I have a function in ASP that returns a TXT file.
I want the user to download the file but the browser wanted to keep displaying it when I did Response.Redirect("/Dir/Dir/TextFilePath.txt");
So I discovered that if you add this to the header it forces a download
Response.AddHeader("content-disposition",
"attachment;filename=/Dir/Dir/TextFilePath.txt");
And this DOES force download the file, with one catch.
The file is the aspx source code and not my txt file.... It's named correctly but it is most definitely not the txt file.
here is a correct way to download files in asp.net.
note the 'a correct way' and not 'the correct way', you can do it in other ways but this one works for me.
try
{
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.AddHeader("content-disposition", "attachment; filename=" + _Filename);
Response.AddHeader("Content-Type", "application/Word");
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Length", _FileLength_in_bytes);
Response.BinaryWrite(_Filedata_bytes);
Response.End();
}
catch (ThreadAbortException)
{ }
finally
{
}
the example above transmits a word file by sending it as a byte array.
you dont have to do it this way, but it works.
also i would like to add for anyone who decides to use my method,
this WILL throw a ThreadAbortException at Response.End().
its a known issue and it affects nothing, everything is being executed correctly but the exception is still thrown, so it must be caught.
You can't affect the headers of the URL supplied for the redirect from the page where the redirect was issued from. I suspect that you actually want to do something like:
var responseText =
File.ReadAllText(Server.MapPath("~/Dir/Dir/TextFilePath.txt"));
Response.ContentType="text/plain";
Response.AddHeader("content-disposition",
"attachment;filename=TextFilePath.txt");
Response.Output.Write(responseText);
Response.End();
Have you tried something like this?
this.Response.AddHeader("content-disposition", "attachment;filename=" + file);
Response.TransmitFile( Server.MapPath(fileName) );
Response.End();

.net CSV file stream to browser loosing characters on production server

I've got basic functionality to stream a file to the browser which invokes a "Save As". The output is dynamically generated and stored within a string and not a file saved on the server.
See code below.
string output = GenerateCSVDdata;
Response.Clear();
Response.ClearHeaders();
Response.AddHeader("Content-Disposition", "attachment; filename=\"test.csv\");
Response.ContentType = "application/octet-stream";
Response.BinaryWrite(System.Text.Encoding.UTF8.GetPreamble());
Response.Write(output);
Response.End();
Now, on my development server, the CSV fully downloads. On the production server, the last few characters on end are cut off. The larger the CSV, the more characters are missing. I've tried so many different things like Response.Flush etc but nothing can fix it. The only thing I can do is throw a load of empty chars on the end in hope nothing gets cut.
Is there something quite wrong with this method of streaming a file download without actually saving the file to disk?
Thanks for your help.
Can you determine if there is a difference in the byte count for the .csv file you are using?
byte[] defaultEncodingBytes = System.Text.Encoding.Default.GetBytes(defaultEncodingFileContents);
byte[] UTF8EncodingBytes = System.Text.Encoding.UTF8.GetBytes(defaultEncodingFileContents);
Try this, it worked for me.
void DownloadFile(string filename)
{
//string filename = "c:\\temp\\test.csv";
byte[] contents = System.IO.File.ReadAllBytes(filename);
Response.Clear();
Response.ClearHeaders();
Response.AppendHeader("Content-disposition", String.Format("attachment; filename=\"{0}\"", System.IO.Path.GetFileName(filename)));
Response.AppendHeader("Content-Type", "binary/octet-stream");
Response.AppendHeader("Content-length", contents.Length.ToString());
Response.BinaryWrite(contents);
if (Response.IsClientConnected)
Response.Flush();
}
Regards.

C# Writing to the output stream

This code will always make my aspx page load twice. And this has nothing to do with AutoEventWireup.
Response.Clear();
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "inline;filename=data.pdf");
Response.BufferOutput = true;
byte[] response = GetDocument(doclocation);
Response.AddHeader("Content-Length", response.Length.ToString());
Response.BinaryWrite(response);
Response.End();
This code will only make my page load once (as it should) when I hardcode some dummy values.
Response.Clear();
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "inline;filename=data.pdf");
Response.BufferOutput = true;
byte[] response = new byte[] {10,11,12,13};
Response.AddHeader("Content-Length", response.Length.ToString());
Response.BinaryWrite(response);
Response.End();
I have also increased the request length for good measure in the web.config file.
<httpRuntime executionTimeout="180" maxRequestLength="400000"/>
Still nothing. Anyone see something I don't?
GetDocument(doclocation);
May be this method somehow returns Redirection code ? or may be an iframe or img for your dynamic content?
If so:
In general the control could get called twice because of the url response. First it renders the content. After that your browser tries to download the tag (iframe,img) source which is actually a dynamic content that is generated. So it makes another request to the web server. In that case another page object created which has a different viewstate, because it is a different Request.
Have you found a resolution to this yet? I having the same issue, my code is pretty much a mirror of yours. Main difference is my pdf is hosted in an IFrame.
So interesting clues I have found:
If I stream back a Word.doc it only gets loaded once, if pdf it gets loaded twice. Also, I have seen different behavior from different client desktops. I am thinking that Adobe version may have something to do with it.
Update:
In my case I was setting the HttpCacheability to NoCache. In verifying this, any of the non client cache options would cause the double download of the pdf. Only not setting it at all (defaults to Private) or explicitly setting it to Private or Public would fix the issue, all other settings duplicated the double load of the document.
Quick Guess: Could it be that at this stage in the page life cycle, the class that contains GetDocument() has already gone through garbage collection? The ASP.NET Worker process then needs to reload the page in order to read that method again?
Have you tried it in the Page_Load ? and why is GetDocument a static method?

Categories