I need to display files in a HTML page in an object tag.
I use C# MVC4 to send the file. In my code, I set the "Content-Type" and "Content-Disposition" headers.
When I set the Content-Type to something Chrome dosen't know, it will download the file, regardless of the "Content-Disposition" header.
HTML:
<div>
<object data="http://localhost/UncHelper?path=secrectPath\file.dwg"></object></div>
C#:
public override void ExecuteResult(ControllerContext context)
{
context.RequestContext.HttpContext.Response.AddHeader("Content-Type", _contentType);
context.RequestContext.HttpContext.Response.AddHeader("Content-Disposition", "inline; filename=\"" + _fileName + "\"");
context.HttpContext.Response.WriteFile(_uncPath);
context.HttpContext.Response.End();
}
When I try to display a pdf file (_contentType = application/pdf) everything is fine.
But when I try to display a .dwg (_contentType = application/dwg) Chrome will download the file. How can I prevent this?
(I don't want to set a HTML status of 203 based on the browser or anything like that.)
Thanks!
This is not possible, and is also a slight misunderstanding on your part i think. For a browser to be able to display a file, it first has to be downloaded.. This goes for all file types. For instance, if you were displaying an image of image/jpeg, with the disposition set to inline, the browser still downloads the image, and then displays it inline, instead of asking the user where he/she would like to save it. If the browser has no knowledge of how to display the file, this is not an option, and will default to the only other option, which is to ask the user where to save it.
Related
I would like to change the "page title" for the openned window when a user views an ashx file in the browser. Users click on a document which will open in a new tab in the browser, and the document is shown (i.e. Word, Excel, PDF, etc.). What happens now, is that the page title shows something like "file.ashx?id=5" when I would rather the title show something like "New Document.pdf" or just "New Document" instead of showing the url of the ashx file.
I have looked into setting the filename through a header, that does work, but the file is downloaded instead of simply openning in the broser window. That is not the desired behavior I was going for.
I understand that this may not be possible, but thought I'd check anyway.
Thanks for the help.
For the title of the page: I can only speak to Internet Explorer, but when you show a new window, Internet Explorer requires that the title bar always be displayed (see the MSDN Article About Window Restrictions for more details). The problem when viewing files inline is that you do not send any HTML back to the page so there is no way through this method to have the title change.
I know that we did experiment with several different approaches, but decided that for our user base, it was ok to not have a user-readable value in the title bar. If this is important to you, then I think your only real option would be a frame-based solution where your ashx page is embedded in a frame (or iframe) and the title page is controlled by content in a different frame (or portion of the page in the event you use an iframe).
To view the file in the browser instead of having it downloaded: you need to set the Response ContentType to the appropriate MimeType for the file (i.e. "application/pdf" for PDF files) and add a Content-Disposition header that specifies the file is to be opened inline and the file name for the user. You should also ensure that other content and headers are cleared from the response.
this.Context.Response.ClearContent();
this.Context.Response.ClearHeaders();
this.Context.Response.ContentType = "application/pdf";
this.Context.Response.AddHeader("Content-Disposition", "inline; filename=mytest.pdf");
this.Context.Response.TransmitFile(sLocalFileName);
this.Context.Response.Flush();
In an ASP.NET 2.0 application, using Google Chrome 13 on Windows.
My app dynamically generates a PDF report when the user browses to a particular aspx page. For the most part, things work fine on various browsers.
However, on Chrome, when Chrome's PDF viewer is being used, the following can happen :
- the user presses the floating diskette icon on the bottom right hand side of the viewer to save the PDF document. The file is saved with the aspx page's name. e.g. Report.aspx .
If I open that downloaded aspx file in Adobe Reader, it opens up ok as a PDF document. But is there a way to get chrome to default the name of the file to save to have a ".PDF" extension ?
EDIT :
The code for the report generation page looks something like this :
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.ContentType = "application/pdf";
byte[] data = GenerateReportHere(); // dynamically generate PDF report
Response.AddHeader("Content-Length", data.Length.ToString());
Response.BinaryWrite(data);
Response.Flush();
Response.End();
}
Note that I don't want to use a "Content-Disposition" header like :
Response.AddHeader("Content-Disposition", "attachment; filename=Report.pdf");
because that causes the browser to ask the user if they want to download the file. In Chrome it won't display it in its PDF viewer - just gives the user the chance after downloading to open the file using whatever program they have associated with the ".pdf" file extension.
You should try using content-disposition header while streaming the PDF file to the browser. For example,
HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=[ReportName].pdf");
// Code to stream pdf file content to the client
...
For more info about content disposition, see
http://www.jtricks.com/bits/content_disposition.html
http://greenbytes.de/tech/webdav/draft-reschke-rfc2183-in-http-latest.html
Since chrome is up to date with HTML5, we can use the shiny new download attribute!
Works
There is many similar questions but there is still no clear answer that is solving the problem taking some action after writing some stream to response.
I have a following situation:
On button click I am generating some excel file that I am going to write to response allowing user to download generated file. Imidietly after clicking the button, I am disabling it, to prevent double clicking this button. In Page-Load event handler I have following code:
GenerateBTN.Attributes.Add("onclick", "this.disabled=true;" + ClientScript.GetPostBackEventReference(GenerateBTN, "").ToString());
After Page_Load eventhandler, GenerateBTN_Click handler executes the code needed for generating the file and at the end of this method (handler) I am response writing generated file with following code:
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
Response.WriteFile(#"C:\Reports\" + filename);
Response.End();
The Save As dialog appears and user can download the generated file, but the problem is that the disabled GenerateBTN remains disabled. How to enable it afer Writing generated file to response? I understand that afer clearing current response I can not continue with the initial Response, but is there any way to solve this problem?
You can put an IFrame on the page and set it's visiblity to hidden. Have your button load the file in the IFrame and use Javascript to detect if the IFrame is still loading or not. When the loading is done, enable your button.
Can't supply a code example at the moment, but if you decide to go this route and need a sample, let me know I will update this answer.
Edit for 2nd answer
What you want to do is create a file like "Download.aspx" that you pass in the file name as a querystring parameter. This way, you can have your server get the file from a location outside of the Web Application's path and adjust the header to force a file download.
Download.aspx
using System.IO;
protected void Page_Load(object sender, EventArgs e)
{
string FileName = Server.UrlDecode(Request.Params["FileName"]); //Example: "MyFile.txt"
Response.AppendHeader("Content-Type", "application/force-download");
Response.AppendHeader("Content-Disposition", "attachment; filename=" + FileName);
Response.WriteFile(#"C:\MyFolder\" + FileName);
}
You would load the page by calling something like "Download.aspx?FileName=MyFile.txt"
You will need to add checks to make sure the file exists and the querystring parameter exists, but that should force the download and allow you to get the file from another location. When you use an ASPX page to serve the file, you can also do credential checks to see if the user is logged into your site (if you have login logic already) or log the download to a log file/database if you want to keep track of it. It gives you a lot more control over the download process.
As for the IFrame loading code, I'm not 100% sure how this works with a file download, but what I was originally thinking was something like this -- view source on: http://sykari.net/stuff/iframe.
Wrap the button in an UpdatePanel, then simply toggle its enabled property before and after the file work.
You can put an IFrame on the page and
set it's visiblity to hidden. Have
your button load the file in the
IFrame and use Javascript to detect if
the IFrame is still loading or not.
When the loading is done, enable your
button.
Can't supply a code example at the
moment, but if you decide to go this
route and need a sample, let me know I
will update this answer.
I've decided to use your suggestion.. but i still have some questions regarding this problem...
Is it possible to load .txt files in iframe?
Is it possible to load some files that are not included in web application's folder?
The problem with loading txt files in iframe is it does not trigger save as dialog to appear, instead of that file content is displayed inside that iframe.
For loading files into an iframe I've used following code:
HiddenFrame.Attributes["src"] = /GeneratedFiles/ + "test.zip";
You can see that I've had to use relative path and my file has to be included in web app's virtual folder.
What is the best javascript (jquery) eventhandler (function) to detect when Iframe has finished loading? I've used jquery function:
$("#ctl00_ContentPlaceHolder1_HiddenFrame").ready(function () {
if ($("#ctl00_ContentPlaceHolder1_HiddenFrame").attr('src') != '') {
$('#ctl00_ContentPlaceHolder1_GenerateSapFilesBTN').removeAttr("disabled");
}
});
But it appears that button is being enabled before Save As dialog actually appears.. Is it possible to solve this problem with this type of eventHandler or do I have to use some other function...
EDIT 2
It appears that moving the object tag in the Dom is the cause of the problem. I added an iframe directly to the page and it works fine without any problems.
However, when I move that iFrame into a modal dialogue box (http://www.ericmmartin.com/projects/simplemodal/) the PDF disappears (the object tag no longer renders correctly).
So it appears that it's no longer a question about my handler, but more a question about why moving the "object" (or embed) tag in the DOM (which lives inside an iFrame) causes it to "blank-out."
Also, when the pdf is moved from the modal dialogue back to its original position, it appears correctly. So, perhaps I should focus more on the modal dialogue itself.
Thoughts? Thanks for your suggestions thus far.
EDIT 1
So I've made some modifications for testing.
I've got the iframe to output an object tag for pdf requests along with the server time.
Response.AddHeader("content-type", "text/html");
WebClient client = new WebClient();
Response.Write("<html><head></head><body><h1>"+ DateTime.Now.ToString() + "</h1><object height='100%' width='100%' name='plugin' data='" + Request.Url.ToString() + "&embed=true' type='application/pdf' /></body></html>");
Response.Flush();
Response.Close();
Response.End();
Now I get a page with the current time correctly, but the object only displays the PDF the first time after I publish the aspx page. So it appears to be some sort of caching issue? Except that the object isn't loading anything (not even the previously loaded PDF).
If right click on the iframe and refresh the page, the object loads up fine. (The same is true if I use an embed tag).
Original Question
I know there are a lot of questions on this...
streaming PDF data through an ASPX page
Server generated PDF not displaying in IFrame on aspx page on some (but not all )PCs
Displaying a PDF Document in ASP.net page
But they either weren't answered, or the answer didn't work.
Environment
.Net 4
Adobe 9.3.4
IIS 5.1
XP sp3
VS 2010
IE 8.0.6001.18702
Background
The pdf's I'm streaming come from a storage repository where the files don't have any extensions (this is done for security). I look up the file in the database and stream it back to the client via the following code:
Response.Clear();
WebClient client = new WebClient();
Byte[] buffer = client.DownloadData(sPath);
Response.AddHeader("content-length", buffer.Length.ToString());
Response.AddHeader("content-disposition", "inline;filename=" + fileName);
Response.AddHeader("expires", "0");
Response.AddHeader("Content-Type", "application/pdf"); //this is usually dynamic to support other types (doc, xls, txt, etc.)
Response.OutputStream.Write(buffer, 0, buffer.Length);
Response.Flush();
Response.Close();
Response.End();
This works for every file type (doc, txt, xls, html) when used directly in the browser or in the iframe (displayed as a modal popup) with the exception of pdf files. They do not work reliably when accessed via the iframe, but work fine when accessed directly in the browser.
The only time it does work is the first time I request a document after I publish the aspx page that is serving these files. All subsequent hits return a blank page (even from new tabs or browser windows). Firefox reliably displays the pdf every time regardless.
Attempted Solutions
I've tried various ways I of streaming the file:
Response.TransmitFile(sPath);
Response.WriteFile(sPath);
//As well as some others
I've tried adding .pdf to a parameter at the end of the request
http://www.myurl.aspx?File=test.pdf
I've tried making the URL unique by adding a time stamp
http://www.myurl.aspx?File=test.pdf&Unique=Friday__September_17__2010_12_02_16_PM
Un-Attempted
I've read about IIS compression causing problems, but it was for a newer version of IIS.
Didn't try using embed tag since I would like to stick to the iFrame if possible (The existing infrastructure uses it).
Any help would be greatly appreciated!!!
Thanks.
I had a similar problem that arose when the PDFs were streaming over SSL (IE only, FF didn't exhibit the issue) that was only solved by doing the following:
Response.ClearHeaders();
Response.ClearContent();
Response.Buffer = true;
Response.AppendHeader("Content-Disposition", "inline; attachment; filename=Filename.pdf");
Response.ContentType = "application/pdf";
Response.WriteFile(path);
Response.Flush();
Response.End();
So I gave up and decided to use a standard IE popup window instead.
window.open(URL, 'Window', 'height=' + pageHeight + ',width=' + pageWidth + ',top=0,left=0,resizable');
I had to render the pdfs in an object tag and everything else inside an iframe within the popup for it to work, but it works...
if (sDocType == "pdf")
{
Response.AddHeader("content-type", "text/html");
WebClient client = new WebClient();
Response.Write("<html style='margin:0px;padding:0px;'><head></head><body style='margin:0px;padding:0px;'><object height='100%' width='100%' name='plugin' data='" + Request.Url.ToString() + "&embed=true' type='" + zGetContentType(HttpContext.Current.Request.QueryString["docType"]) + "'><param name='src' value='" + Request.Url.ToString() + "&embed=true' />alt : <a href='" + Request.Url.ToString() + "&embed=true'>View</a></object></body></html>");
Response.Flush();
Response.Close();
Response.End();
}
else
{
Response.AddHeader("content-type", "text/html");
WebClient client = new WebClient();
Response.Write("<html style='margin:0px;padding:0px;'><head></head><body style='margin:0px;padding:0px;'><iframe frameborder='0' scrolling='no' height='100%' width='100%' src='" + Request.Url.ToString() + "&embed=true' /></body></html>");
Response.Flush();
Response.Close();
Response.End();
}
I'm not sure that you need to set the filename, especially if it doesn't have the .pdf extension. When streaming PDFs to browser in the past, I've always used this code:
Response.Clear();
Response.ContentType = "application/pdf";
Response.BinaryWrite(pdfBuffer);
Response.Flush();
Otherwise, there's a possibility that something has hosed over the registry settings for the application/pdf CLSID on the client computer.
I was able to solve a similar problem (pdf inside of modal window internet explorer)
by taking out the iframe. Instead, load the pdf into an html object element.
see the link below:
http://intranation.com/test-cases/object-vs-iframe/
To sum it up:
The setup that did not work:
jQuery floatbox, loads html fragment with iframe, load aspx page into iframe, load pdf into aspx page
The setup that now works:
jQuery floatbox, loads html fragment, append object element.
before appending the object element, set data
attribute of object element to the aspx page url
I am using ASP.NET2.0. I have created a download form with some input fields and a download button. When the download button is clicked, I want to redirect the user to a "Thank you for downloading..." page and immediately offer him/her the file to save.
I have this following code to show the savefile dialog:
public partial class ThankYouPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.AddHeader("Content-Disposition",
"attachment; filename=\"downloadedFile.zip\"");
Response.ContentType = "application/x-zip-compressed";
Response.BinaryWrite(this.downloadedFileByteArray);
Response.Flush();
Response.End();
}
}
Obviously, this code does not allow to display any "Thank you" message. Is there an "AfterRender" event or something similar of the Page where, I could move this download code and give a chance for the page to render the "thank you" message to the user? After all, I am truely thankful to them, so I do want to express that.
You could reference a download page from your thank you page using an IFrame
<iframe src="DownloadFile.aspx" style="display:none;" />
In this case, DownloadFile.aspx would have the code behind from your example.
Use a META REFRESH tag in the head of your thank-you page:
<META http-equiv="refresh" content="1;URL=http://site.com/path/to/downloadedFile.zip">
Alternatively, you might use a body onLoad function to replace the current location with the download URL.
<body onLoad="document.location='http://site.com/path/to/downloadedFile.zip'">
In this case the redirection will start after the current page has finished loading and only if the client has JavaScript enabled, so remember to include a link with a download link ("If your download doesn't start in a few seconds..." and so on).
You may also use an IFRAME as suggested by Phil, or even a FRAME or a full-blown pop-up (blockable, mind you). Your mileage may vary.
The code you've written, should actually be redirected to from the 'thank you' page (making it the 2nd redirect). Because you've set the content disposition to attachment, this page will not actually replace the existing 'thank you' page.
if you want to serve a "Thank You" page and the file the client must call twice the server.
So you can just create the thankyou.aspx page for displaying the message (and maybe put a direct download link to the file).
You can start download with a meta tag or just using js (even ms do the same for their download page).
Then to serve the file you sould create a direct link to avoid another page run on the server; otherwise you should create an HttpHandler just to hide the filesys.
The file should be sent to the client with Response.TrasmitFile
Please check the following link, this may help you to sort out your issue.
In Asp.net, on button click, how to open a download dialog, and then redirect the user to another page?