Download an Excel file - c#

I have read some past posts here on how to download a Excel file from a website. So, I have setup the below code:
string path = MapPath(fname);
string name = Path.GetFileName(path);
string ext = Path.GetExtension(path);
string type = "application/vnd.ms-excel";
if (forceDownload)
{
Response.AppendHeader("content-disposition",
"attachment; filename=" + name);
}
if (type != "")
{
Response.ContentType = type;
Response.WriteFile(path);
Response.End();
}
However, I get no download dialog box.
I try this both in IE 8 and FireFox 10.0.2.
The file is there, it's not locked, and it's not set to read only.
I'm not sure were I went wrong.

According to this link, you need to add this line:
strFileName = Path.GetFileName(path);
Response.TransmitFile( Server.MapPath(strFileName) );
This will cause a Open / Save As dialog box to pop up with the filename of SailBig.jpg as the default filename preset.
This of course assumes you're feeding a file that already exists. If you need to feed dynamically generated - say an image [or any file] that was generated in memory - you can use Response.BinaryWrite() to stream a byte array or write the output directly in Response.OutputStream.
EDIT:
Microsoft's MSDN site has a detailed explanation about File Downloading. It includes both samples for Java and .Net applications, the concept is the same:
Get the response.
With the response:
Set the content type to "APPLICATION/OCTET-STREAM" (it means there's no application to open the file).
Set the header to "Content-Disposition", "attachment; filename=\"" + + "\"".
Write the file content into the response.
Close the response.
So, looking at the MSDN ASP.Net file download, you're lacking the 2.3 step. You're just writing the file name to the response.
// transfer the file byte-by-byte to the response object
System.IO.FileInfo fileToDownload = new
System.IO.FileInfo("C:\\downloadJSP\\DownloadConv\\myFile.txt");
Response.Flush();
Response.WriteFile(fileToDownload.FullName);
With this example you will download your file successfully, of course if you can get the file with no problems :).
EDIT 2:
The HTML component used to download any file must be a regular HTML Request. Any ajax request to download a file won't work. Microsoft explains that here. And the main quote:
Its impossible to attach an event before and after a download through javascript. Browser doesn't allow this type of events for security reasons.

You need to send this before the file attachment header:
Response.ContentType = "application/vnd.ms-excel"
See: Export data to excel file from Classic ASP failing

Try adding such HTTP headers
Content-Type: application/force-download
Content-Type: application/vnd.ms-excel
Content-Type: application/download

Related

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

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[]

Prompt user to save/open file in ASP.NET C#

It shouldn't be this hard to find out how to do this. Basically I'm trying to take a string and let the client save it when they click a button. It should pop up with a Save/Open dialog. No extra bells and whistles or anything. It's not rocket science, (or so I would've thought).
There seems to be a ton of different ways, (StreamWriter, HttpResponse, etc.), but none of the examples I've been able to find work properly or explain what's going on. Thanks in advance.
An example one of the many blocks of code I've found...
(This is just an example, feel free to not base your answer around this.)
String FileName = "FileName.txt";
String FilePath = "C:/...."; //Replace this
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "text/plain";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName + ";");
response.TransmitFile(FilePath);
response.Flush();
response.End();
Line 2 says to replace that string. How? This code was advertised as bringing up a dialog. I shouldn't be having to set a path in the code, right?
EDIT: Final Outcome (Edited again, Delete has to come before End();)
string FilePath = Server.MapPath("~/Temp/");
string FileName = "test.txt";
// Creates the file on server
File.WriteAllText(FilePath + FileName, "hello");
// Prompts user to save file
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "text/plain";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName + ";");
response.TransmitFile(FilePath + FileName);
response.Flush();
// Deletes the file on server
File.Delete(FilePath + FileName);
response.End();
Line 2 (FilePath) indicates the path to the file on the server
Line 8:
response.TransmitFile(FilePath);
Transmits that specific file to the client and THAT is what pops the save dialog.
If you don't transmit the file, I'm not sure if the dialog will pop up at all (even though you set a header)
Anyways, I think line 8 should read:
response.TransmitFile(FilePath + FileName);
There will be a default dialog box by browser, if it will find Response as some file. If you want browser to display that default dialog box, all you need to do is send response to browser as file, which you can do in number of ways:
If it is a static file,
best way is to just mention path of file in anchor tag's href.(obviously if you don't have security concern)
Just out along with your response, the way it is done in your example.
Other ways you can refer here 4 ways to send pdf from asp.net
If it is a dynamic file which you need to generate at run time, you can do a trick, generate the file from filestream, put it in some temporary folder at server, read it back as a static file as mentioned above.
Just use this code it should work to prompt the user to open a dialog for opening or saving the file on the system ....
byte[] bytesPDF = System.IO.File.ReadAllBytes(#"C:\sample.pdf");
if (bytesPDF != null)
{
Response.AddHeader("content-disposition", "attachment;filename= DownloadSample.pdf");
Response.ContentType = "application/octectstream";
Response.BinaryWrite(bytesPDF);
Response.End();
}
FilePath is supposed to point to the file you want to send to the client. This is the path on the server.

save as dialog in asp.net

I have some data in the form of a string. I want to write this data to a file and save the file to the specified path. The path would be specified by opening a save as dialog on the button click. How can this be achieved??
The file is saved into the server initially with this code
string getnote = txtdisplay.Text.Trim();
String filepath = Server.MapPath(#"img\new1.txt");
System.IO.FileStream ab = new System.IO.FileStream(filepath, System.IO.FileMode.Create);
System.IO.StreamWriter Write101 = new System.IO.StreamWriter(ab);
Write101.WriteLine(getnote);
Write101.Close();
Response.ClearContent();
From the server get the file as attachment.Use the following code for save as dialog box for downloading or saving the file. The file will save by default in the download folder. To save to the specified location change the browser settings.
Response.ContentType = "text";
Response.AppendHeader("Content-Disposition", "attachment; filename=new1.txt");
Response.TransmitFile(Server.MapPath("~/img/new1.txt"));
Response.End();
Response.ContentType = "application/octet-stream" (or content type of your file).
Response.AppendHeader("content-disposition", "attachment;filename=" & strFileName)
There is no Save As dialog in ASP.NET.
Remember, your ASP.NET application is running in a browser on a user's computer. You have no access to the user's file system, including the Save As dialog.
However, if you send the user a file, as an attachment, most browsers will display a dialog asking the user whether to save the file or open it. Maybe the user will choose to save it. That's what the example from phoenix does.
You could use a LinkButton (or regular link) and have the url point to a handler (ASHX) that retrieves the data and sends back a response with content disposition set to attachment. Write the data to the response. You'll also need to set up some other headers in the response -- such as content type and length. This would give the document (file) a regular link that could perhaps be bookmarked (if a regular link) in the future so that it can be retrieved again. You'd need to pass enough data in the query string to be able to identify which data is to be downloaded.
if I userstand you correctly, here -
saveFileDialog1.DefaultExt = "*.file";
saveFileDialog1.Filter = "File|*.file|Other File|*.OFile|";
if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK &&
saveFileDialog1.FileName.Length > 0)
{
WebClient wc = new WebClient();
wc.DownloadFile("http://www.exaple.com/exaplefile", saveFileDialog1.FileName);;
}

Change name of file sent to client?

I have a webpage that pulls information from a database, converts it to .csv format, and writes the file to the HTTPResponse.
string csv = GetCSV();
Response.Clear();
Response.ContentType = "text/csv";
Response.Write(csv);
This works fine, and the file is sent to the client with no problems. However, when the file is sent to the client, the name of the current page is used, instead of a more friendly name (like "data.csv").
My question is, how can I change the name of the file that is written to the output stream without writing the file to disk and redirecting the client to the file's url?
EDIT: Thanks for the responses guys. I got 4 of the same response, so I just chose the first one as the answer.
I believe this will work for you.
Response.AddHeader("content-disposition", "attachment; filename=NewFileName.csv");
You just need to set the Content-Disposition header
Content-Disposition: attachment; filename=data.csv
This Microsoft Support article has some good information
How To Raise a "File Download" Dialog Box for a Known MIME Type
Add a "Content-Disposition" header with the value "attachment; filename=filename.csv".
Response.AddHeader("content-disposition", "attachment; filename=File.doc")

Categories