I've following code for file download:
FileInfo fileInfo = new FileInfo(filePath);
context.Response.Clear();
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + System.IO.Path.GetFileName(filePath));
context.Response.AddHeader("Content-Length", fileInfo.Length.ToString());
context.Response.WriteFile(filePath);
context.Response.End();
When I run it on my local IIS6 it works fine. Web browser (tested on IE8, Firefox 3.5.2, Opera 10) shows file length before I start download the file.
When I run this code on remote IIS7, web browser doesn't shows file length. File length is unknown.
Why I don't get file length when this code runs under IIS7?
Use Fiddler to check what is actually sent. My guess is you are getting chunked encoding as a result of buffering being set to false on the IIS7 server.
BTW, drop the Response.End call its quite a traumatic thing to do and is unnecessary (for that matter so is the call to Clear).
Edit
Strictly speaking when streaming content with chunked encoding (which is desirable in your scenario) the Content-Length header ought not be present (see RFC2616 Section 4.4.) It seems to me that IIS7 takes it upon itself to enforce this. In fact I've had a Classic-ASP scenario in which IIS7 throws an error when COM code tries to add a Content-Length header when buffering is off.
This is really annoying because despite what the committee in the ivory towers would like, this header give the end user a very useful piece of info.
Thanks for this post.... I got it working for IE with the first line.
public void WriteCSV(string strData) {
//Required for IIs7 WS2008R2 fix
Response.ClearHeaders();
Response.Clear();
Response.Buffer = true;
Response.ContentType = "application/csv";
Response.AddHeader("Content-Disposition", "attachment;filename=report.csv");
Response.Write(strData);
Response.Flush();
Response.End();
}
Related
I'm having a piece of code which downloads excel of Invalid records after Import.
I want to refresh a grid after this kind of partial successful import. But, code after excel auto download is not executing.
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.AddHeader("content-disposition", "attachment; filename=" + PathToExcelFile);
Response.AddHeader("Content-Type", "application/Excel");
Response.AddHeader("Content-Length", file.Length.ToString());
Response.WriteFile(file.FullName);
HttpContext.Current.Response.Flush(); // Sends all currently buffered output to the client.
HttpContext.Current.Response.SuppressContent = true; // Gets or sets a value indicating whether to send HTTP content to the client.
HttpContext.Current.ApplicationInstance.CompleteRequest();
I had found that Response.Flush() will throw an Thread Abort exception. Hence changed it to CompleteRequest(). But, still no luck.
Not sure what I'm doing wrong?
Save the file name/path etc. to ViewState variables, then call window.open to a separate download.aspx page which processes the downloading of the file. In the Download page reference the ViewState variables you previously set. In the original (not the download) page you can execute what ever code you like after the window.open call.
We have an ASP.NET application which dynamically generates Excel documents and streams them to the client, using Response.WriteFile, see code below. Note that the document is deleted once the file has been written to the client. Thus, no documents are ever left on the server.
However, my client's users has now all upgraded to Office 2010, and now the documents will open in "Protected View". In order to edit the document, the user has to click "Enable editing" first. This is considered unacceptable for the users.
The reason that this happens is that streamed documents are placed in the Temporary Internet files, and this is considered a "potentially unsafe location". And documents in such locations are opened in protected view. I am just hoping there is some way to work around this.
Theoretically, I could place the document in a folder which is accessible from the client, and redirect to the document.
This solution is not an option, however. Firstly, since the document would be left on the server, it could be accessible for other users, which is a problem since the documents may contain confidential data.
There are other reasons why this is not a vialable option.
An other theoretical workaround would be to ask all users to disable the setting "Enable protected view for files located in potentially unsafe locations". Naturally, this is not an option either.
So, in short, is there anyway to avoid the documents to be opened in "Protected view" while using the streaming technique described below?
Response.Buffer = true;
Response.Clear();
Response.AddHeader("Pragma", "no-cache");
Response.Expires = 0;
Response.AddHeader("Content-Type", contentType);
Response.AddHeader("Content-Disposition", "attachment; filename=" + proposedFilename);
Response.WriteFile(dstFullPathName);
Response.Flush();
Response.Close();
File.Delete(dstFullPathName);
HttpContext.Current.ApplicationInstance.CompleteRequest();
I have a method that returns a byte array. I then write this array to the output stream as an excel file. Some users are reporting "Internet Explorer was not able to open this internet site" errors in ie7.
I don't get this error when I run it in the test environment (using ie9). However sometimes the first time I click the link, Excel will open but I'll receive an error the reads "there was a problem sending the command to the program" and the file doesn't load into Excel. If I click the link a second time, the file will open in Excel fine. Here's the code that send the byte array through the response stream, after the user clicks a link on a page.
byte[] buffer = GetBinary();
Response.ContentType = "application/vnd.ms-excel";
Response.Buffer = true;
Response.Expires = 0;
Response.AddHeader("Content-Type", "application/vnd.ms-excel");
Response.AddHeader("Content-Length", buffer.Length.ToString());
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.AddHeader("Content-Disposition", "attachment;filename=xx.xls");
Response.BinaryWrite(buffer);
Response.End();
If it makes any difference, the link they click opens up a new window, and the above block of code executes in the page_load event of the new page. What could be causing these errors? I've used similar code before with no issues.
I have an XDocument object that needs to be downloaded by the client. This xml will be generated on page_load and then sent to the user as a download.
I cant figgure out how to send the object to the client without having an acctual file.
Any ideas?
As stated i checked this other post not quite the same but close enough.
Response.Clear();
Response.ContentType = "text/xml";
Response.AppendHeader("Content-Disposition","attachment;filename=" + DateTime.Now+".xml");
Response.Write(doc.ToString());
Response.End();
I have an ASP.net application which returns a binary PDF file (stored from the database, which was previously uploaded) to the client.
The code I have works fine for all browsers, except for internet explorer 6 (story of my life!). In IE6, when a user clicks open, Adobe reports the error: "There was an error opening this document. The file cannot be found."
When the user clicks save, the PDF saves fine and can be opened by double clicking it. I am stumped. Google has given suggestions of caching (setting cachecontrol to private etc) and I have tried all of those but nothing has worked.
The wierd(er) behaviour is when I generate a PDF in my ASP .net server layer (using NFop) from scratch, IE will open it fine (using the SAME code!).
Here is my code for sending the binary data across the wire:
// Firefox doesn't like spaces in filenames.
filename = filename.Replace(" ", "_");
string extension = Path.GetExtension(filename);
string contentType;
switch (extension)
{
case "pdf":
contentType = "application/pdf";
break;
default:
contentType = "application/x-unknown";
break;
}
context.Response.Clear();
context.Response.AddHeader("content-disposition", "attachment;filename=" + filename);
context.Response.Charset = "";
context.Response.ContentType = contentType;
context.Response.BinaryWrite(data);
context.Response.Flush();
Here are application versions:
ASP .net 3.5
IE6.0.2900.2180.xpsp_s
List item
p2_gdr.091208-2028
Adobe Reader version 8.0.0
Windows XP SP 2
SQL Server 2008
Any help/suggestions would be much appreciated. Thanks :)
EDIT:
I have plugged in Fiddler to view the headers and sure enough it does appear to be a caching issue. grrr!
When my NFop PDF (the one that works) is uploaded, it is sending cache-control = private.
When my attachment PDF (the one that doesn't work) is uploaded, it sends no-cache.
I have looked in the Response object and both appear to have the same headers when I call context.Response.Flush().
Still stumped!
SOLVED:
Somewhere in our framework was a rogue method which was being invoked using reflection:
///
/// Sets the expiratoin of the request and force no cache
///
protected void SetCacheExpiration(HttpContext context)
{
//sets the cache to expire immediately
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetSlidingExpiration(true);
context.Response.Cache.SetExpires(DateTime.Now);
context.Response.Cache.SetMaxAge(new TimeSpan(0, 0, 0));
context.Response.Cache.SetNoStore();
context.Response.Cache.SetAllowResponseInBrowserHistory(false);
context.Response.Cache.SetValidUntilExpires(false);
context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
}
Thanks for your help, caching! It is interesting that the only browser that actually didn't cache the download (when opened) was IE6.
Here the method I've used before to render in-browser PDFs for IE6. Again... this was for a project where we showed the PDF in the browser, but it should serve you well for a PDF that's shown in the reader.
Somewhere in our framework was a rogue method which was being invoked using reflection:
/// <summary>
/// Sets the expiratoin of the request and force no cache
/// </summary>
protected void SetCacheExpiration(HttpContext context)
{
//sets the cache to expire immediately
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetSlidingExpiration(true);
context.Response.Cache.SetExpires(DateTime.Now);
context.Response.Cache.SetMaxAge(new TimeSpan(0, 0, 0));
context.Response.Cache.SetNoStore();
context.Response.Cache.SetAllowResponseInBrowserHistory(false);
context.Response.Cache.SetValidUntilExpires(false);
context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
}
Thanks for your help, caching! It is interesting that the only browser that actually didn't cache the download (when opened) was IE6.