Exported CSV download stuck in firefox - c#

I'm exporting a CSV to firefox using the following code:
string csv = dataTable.ToCSV();
Response.ClearContent();
Response.AddHeader("Content-disposition", "attachment;filename=solicitud.csv");
Response.AddHeader("Content-length", (Encoding.Unicode.GetBytes(csv).Length).ToString());
Response.ContentType = "application/excel";
Response.ContentEncoding = Encoding.Unicode;
Response.Write(csv);
Response.End();
However, firefox get stucked in "starting" when downloading the files, my guess is that firefox keeps waiting to receive more bytes, this only happens in firefox, IE works fine, Am I missing a header or do you see anything wrong with the code?

Instead use TransmitFile
Writes the specified file directly to
an HTTP response output stream without
buffering it in memory.

Related

Download file with non-english character in C# using HttpResponse

I am trying to build a functionality to download a csv file in C#.
When the name of the file has non-english character, the downloaded file does not seems to have the correct name. However in the network tab, the response header has the same Content-Disposition value, as given in the code.
Sample Code
private void PopulateCsvInResponse(MemoryStream csvData, string fileName)
{
HttpResponse response = HttpContext.Current.Response;
response.Clear();
//actual file name "Москва.csv"
response.AddHeader("Content-Disposition", "attachment; filename=%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0.csv");
byte[] byteArray = csvData.ToArray();
response.AddHeader("Content-Length", byteArray.Length.ToString());
response.ContentType = "text/csv; charset=utf-8";
response.BinaryWrite(byteArray);
response.Flush();
response.Close();
}
For example the file name is Москва.csv.
UTF-8 encoded name : %D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0.csv.
Things that I tried
Replacing Content-Disposition header
Attempt 1
response.AddHeader("Content-Disposition",
"attachment; filename=Москва.csv");
The downloaded file name is
Ð_оÑ_ква
Attempt 2
response.AddHeader("Content-Disposition",
"attachment; filename=\"%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0.csv\"; filename*=UTF-8''%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0.csv");
The downloaded file name is
_%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0.csv_; filename_
Attempt 3
response.AddHeader("Content-Disposition",
"attachment; filename=%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0.csv");
The downloaded file name is
%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0.csv
Attempt 4
response.AddHeader("Content-Disposition",
"attachment; filename*=UTF-8''%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0.csv");
The downloaded file name is
UTF-8''%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0.csv
I finally found out the solution.
The issue was never with above code, it was always working fine.
The actual issue was in front end, where the content disposition header that was received in encode was not decoded, and I skipped to see this part when I raised the question.
I thought of deleting this question, but keeping it so that if someone makes the same silly mistake as me, might realise it earlier instead of wasting time to look for solution for the problem that never existed.

HTML to PDF conversion - Almost works, but

I spent a good part of last few days searching for easy-to-use library that takes a html string as input, and produces PDF output as a file to the client browser.
Of the few dozen tools I tried out, a product called NReco PDF Generator, which is one of many derivative tools based on wkhtmltopdf, seems to suit my needs.
Here's my test code:
var strHtml = String.Format("<h1>Hello World!</h1");
Response.Clear();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=test.pdf");
(new NReco.PdfGenerator.HtmlToPdfConverter()).GeneratePdf(strHtml, null, Response.OutputStream);
Response.End();
With the above code, I expected to see a PDF file being passed to my browser. Instead, I only see the output stream being generated in my developer console. (BTW, I'm using Chrome)
My question is NOT about how the said product works, which I think is working as intended, but it is about whether my code is missing any action for the .NET's Response object or is doing anything wrong. As I already indicated, I can see the converted Pdf stream in the console. I think it's just a matter of capturing that stream in a file and passing it to the client.
The missing line is Response.BinaryWrite(pdfBytes). Without that line the PDF will not be rendered to the user.
As far as I can tell you do not need the lines:
Response.Clear();
Response.ClearHeaders();
The following works for me (Obviously, you need to add using NReco.PdfGenerator;)
string strHtml = String.Format("<h1>Hello World!</h1");
HtmlToPdfConverter pdfConverter = new HtmlToPdfConverter();
var pdfBytes = pdfConverter.GeneratePdf(strHtml);
Response.ContentType = "application/pdf";
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.AddHeader("Content-Disposition", "Inline; filename=TEST.pdf");
Response.BinaryWrite(pdfBytes);
Response.Flush();
Response.End();
Store the PDF as a byte array, then write it to the response.
var pdfBytes = new NReco.PdfGenerator.HtmlToPdfConverter().GeneratePdf(strHtml);
Response.BinaryWrite(pdfBytes);
instead of
(new NReco.PdfGenerator.HtmlToPdfConverter()).GeneratePdf(strHtml, null, Response.OutputStream);
Inspiration for this taken from NReco's site.

ASP.NET MVC cannot stream files

I have a ASP.NET MVC 4 site that creates an excel file using OPEN XML SDK. I simply point the hyperlink to the proper controller and it generates the OPEN XML excel document and writes the stream to response header and done. In IE 9 and Chrome this works fine. File gets downloaded with the given file name and proper contents. However, just recently I upgraded my browser to IE 10 and now instead of downloading the file and opening up in excel I get the error that could not open 'URI'. When I click ok it gives another error: Microsoft Excel cannot access the file 'URI'. There are several possible reasons:
I don't understand why this would work in IE 9 and chrome and not in IE 10. I debugged the response headers with fiddlers and it has the proper content type, and content length set:
Content Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Content Disposition: attachment; filename=result.xlsx
Content length: 1232
Is there something that I am missing?
Code snippet: This all is part of
public override void ExecuteResult(ControllerContext context)
{
...
....
..
extention = "xlsx";
response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
response.AddHeader("Content-Disposition",
String.Format("attachment; filename={0}.{1}", fileName, extention));
response.AddHeader("Content-Length", mem.Length.ToString());
mem.Seek(0, SeekOrigin.Begin); // Go back to the begining.
mem.CopyTo(response.OutputStream);
context.HttpContext.ApplicationInstance.CompleteRequest();
}
As a workaround, Controller.File works for me with ASP.NET MVC 4 and IE 10:
public class DownloadController : Controller
{
public ActionResult GetFile()
{
...
mem.Position = 0;
return File(
mem,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"result.xlsx");
}
}
EDIT
So I have been browsing the MVC source code at CodePlex and found a few implementation details that differ from your code snippet:
Content-Length header is never set
Instead of calling Stream.CopyTo, they use a simple Stream.Read, Stream.Write loop with buffer size of 0x1000
When setting Content-Disposition header, they check whether file download name contains UTF-8 chars, and if so, encode them according to RFC 2231. See ContentDispositionUtil.GetHeaderValue
context.HttpContext.ApplicationInstance.CompleteRequest() is never called
Now you could try applying these changes one by one and see which one makes it work with IE 10.
I guess it's an IE10 bug. But maybe you still can work around it.
Based on this post and a few others.
Please check that:
Both full URI and the filename of Content Disposition header do not contains special symbols and that their lengths are less than 105. Just use regular A-Za-z0-9 symbols for instance.
Try to add "X-UA-Compatible" HTTP header with "IE=9" value.
try these MIME types:-
for old version:-
Response.ContentType = "application/vnd.ms-excel";
Response.AppendHeader("content-disposition", "attachment; filename=myfile.xls");
for 2007:-
Response.ContentType = "application/application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AppendHeader("content-disposition", "attachment; filename=result.xlsx");
for csv files which you need to open in excel is:-
Response.AddHeader "Content-Disposition", "Attachment;Filename=myfile.csv"
in last you can try:-
Response.ContentType = "application/octet-stream";
Response.AppendHeader("content-disposition", "attachment; filename=result.xlsx");
thanks

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

Download Document in the right format without MIME

I have got this WebService that allows uploading/downloading any docs (mostly .docx, .doc, .pdf) and all it returns is byte[] when querying for downloading.
I have written this code
string ContractGUID = dtContract.Rows[0]["ContractGUID"].ToString();
//Get Bytes from WebService
byte[] fileData = BLL.Contract.GetDocument(new Guid(ContractGUID));
Response.Clear();
Response.BinaryWrite(fileData);
Response.AddHeader("Content-Disposition", "Attachment");
Response.Flush();
The other methods that the WebService exposed are GetDocumentName and GetDocumentLen
Is it possible to determine the Mime-Type or force the browser to download it in the right format? Currently it is downloading as .htm in Chrome and when open, I see funny characters. Any better advice?
Thanks.
No, it's not possible to force the browser to download in the right format without you telling it via the Content-Type header.
Response.ContentType = "application/pdf"; //or whatever appropriate
If the web service exposes a GetDocumentName() method you can probably infer the appropriate format by looking at the name, assuming the name has a file extension. This, obviously, is not bullet proof since you can change the extension of a file to anything you want.
Another alternative would be to try and guess the file format by peeking at the first bytes. For example, if the first 4 bytes of the file are 25 50 44 46 then it's very likely that this is a PDF file. On this website, they have a pretty extensive list.
Here's the list of possible content-type headers.
I think, the browser does it through filename.
e.g.:
response.Clear();
response.AddHeader("Content-Disposition", "attachment; filename=" + dbFile.filename.Replace(" ", "_"));
response.AddHeader("Content-Length", dbFile.data.Length.ToString());
response.ContentType = "application/octet-stream";
response.OutputStream.Write(dbFile.data, 0, dbFile.data.Length);
response.End();
dbFile.filename is a string
dbFile.data is a byte[]

Categories