Dynamically Created PDF Not Embedding/Rendering Inline in 64-bit IE9 Window - c#

We're using Reporting Services to generate a PDF report and we need it to be rendered out to the browser window AND embedded in the browser. We've been doing this a long time and it has always worked ... until IE9.
In IE6, IE7, and IE8, we generate the byte array from Reporting Services that represents the PDF report and binary write it out to the browser, and everything works great. The PDF displays embedded in the browser.
In IE9, we try the same exact thing and the PDF is NOT embedded in the browser window. The browser window stays open and is blank/empty, and the PDF is opened in Adobe Reader in a separate window.
Here's a snippet of our code:
try
{
// Set all the Reporting Services variables and parameters and render the report
// ...
byte[] result = rs.Render(format, devInfo, out extension, out mimeType, out encoding, out warnings, out streamIDs);
// Force the render out of the report to the browser
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.AppendHeader("content-length", result.Length.ToString());
Response.AppendHeader("Pragma", "cache");
Response.AppendHeader("Expires", "3600");
Response.Buffer = true;
Response.Cache.SetCacheability(HttpCacheability.Private);
Response.CacheControl = "private";
Response.Charset = System.Text.UTF8Encoding.UTF8.WebName;
Response.ContentEncoding = System.Text.UTF8Encoding.UTF8;
switch (outputformat)
{
case "PDF":
Response.AppendHeader("content-disposition", "inline; filename=report.pdf");
Response.ContentType = "application/pdf";
break;
default:
break;
}
Response.BinaryWrite(result);
Response.Flush();
Response.Close();
Response.End();
}
catch (System.Exception ex)
{
// ...
}
What can we do to get the PDF rendered and embedded in the IE9 broswer window?
Thanks!

hope this might help others, I found a hack/work around of sorts using jquery
function MyFunction(someprams) {
if (navigator.userAgent.indexOf("x64") == -1) {
window.open("yourpage2.aspx?PramName=PramVal, 'winowname', 'window opions here')
} else {
$.get("yourpage1.aspx", { PramName1: PramVal1, PramName1: PramVal1 },
function(data) {
$('#divid').html(data);
});
}
}
so then just add a div to the page :
yourpage1 is the page what calls and streams the pdf and set the cache headers
then yourpage2 is a aspx page that has an ifram on it that i set the src dynamicly :
iframeid.Attributes.Add("src", "yourpage1.aspx?"pram1=" & Request.QueryString("PramVal1") )
note the ifram need a run at server tag, aslo ur probally want it to load the ifram height 100% which u can do
css:
html { height: 100%;}
body { height: 100%;}
html:
<iframe id="iframeid" runat="server" scrolling="no" marginwidth="0" marginheight="0"
frameborder="0" vspace="0" hspace="0" style="overflow: visible; width: 100%;
height: 100%;"></iframe>
what this dose is if user is IE 32 bit then there get a new window open showing the pdf in it (actually in an frame but u cant tell) or if they are IE 64 then skip using window at all and load the page that streams the pdf directly into our page. This forces adobe pdf to open not in a browser window but directly as a pdf so all in all this works and looks ok in both 64 & 32 IE
i did find stream readers caused issues but this works nicely ,
Dim oWebClient As System.Net.WebClient = Nothing
Dim data() As Byte
try
oWebClient = New System.Net.WebClient
data = oWebClient.DownloadData(pdfurl)
//add Response.AddHeader stuff here e.g.
Response.AddHeader("Content-Length", data.Length.ToString)
Response.BinaryWrite(data)

Internet Explorer 64bit can run only 64bit plugins. The Adobe PDF plugin is 32bit and it cannot run in 64bit IE.

Take a look at this forum post:
http://forums.adobe.com/message/3331557#3331557#3331557
Also, this whole thread talks about different fixes to make different versions of IE work. There are multiple things that can cause this issue.
http://forums.adobe.com/thread/758489
One reader also noted that it MUST end in PDF, which it looks like you are doing.
Keep in mind, if you were using different versions of acrobat reader, this issue could actually be related to changes in Reader, and not IE.
In your comment, you noted a 64bit issue. Check out this SO answer re IE8/64bit vista:
Can't display PDF from HTTPS in IE 8 (on 64-bit Vista)
It appears that you're already doing everything that he said he needed to do, in his final answer (namely, setting Cache control to private, and not setting Pragma: no-cache.)
It's interesting to note, that the various responses have gone the way of manually adding the header via:
response.setHeader("Cache-Control","private");
Instead of calling
Response.Cache.SetCacheability(HttpCacheability.Private);
Response.CacheControl = "private";
Unsure there's a difference, but it might be worth a shot.

It is important to note that displaying PDF inline can actually be controlled through Acrobat Reader settings.
In the menu Edit > Preferences..., select Internet from the left-hand navigation and ensure that Display PDF in browser is checked.

It appears that there is a bug in 64 bit IE9; if the file extension being used for the outputStream of the PDF file to be displayed is in UPPERCASE e.g. 'myFile.PDF' instead of lowercase like 'myFile.pdf', the mimeType of the outputStream is not being recognized as application/pdf. It defaults to mimeType text instead. This kind of page does not render at all, or renders partially or renders in some unreadable font. Try using the lowercase .pdf file extension in case it is in uppercase.
Good Luck!

Related

How to force view in browser of pdf and word docs

I am required to open various files types such as pdf and word in browser I see that the most accepted solution seems to be the simlar as to what I have done
public string GetDocument(Guid UserId, string Filename)
{
string mimeType = "application/pdf"
Response.AppendHeader("Content-Disposition", "inline; filename=" + fileName);
return File(doc, mimeType);
}
My quesiton is how do i turn my raw file on the server to something that can be served to the browser I persume I have to change it to byte if so how would one change a pdf to bytes. And for that matter word files
You can use something like:
public void GetDocument(Guid UserId, string Filename)
{
string mimeType = "application/pdf"
Response.AppendHeader("Content-Disposition", "inline; filename=" + fileName);
Response.WriteFile(fileName);
Response.End();
}
Note, Response.WriteFile expects the FULL path to the file, so if the filename variable isn't the full path, you'll need to map it.
In the case of the PDF, most browsers will open in inside the browser, for other file types your mileage may vary, depending on whether the browser has the capability to display that file type inline.
You cannot force it from the server end.
Some browsers (such as Chrome) can render a PDF just fine, but a PDF rendered from a server will only open in Chrome only if the .pdf file extension is associated with Chrome. You can't change the associations without access to the machine on which the browser is running.
As far as I know, you cannot open a Word doc directly in any browser. You have to use a viewer.
Using a viewer you can display PDF or Word docs within the page-- this is different from downloading the file and displaying it natively, but it may suit your purpose.
A few viewers are freely available. Here's two.
Google docs viewer
Office Web Apps viewer

Stream PDF to browser?

Could anyone please tell me how could I stream a pdf to a new tab browser? I just have the pdf stream on memory and I want when I click over the link to show the PDF in a new tab or window browser.
How could I do that?
Thank!!!
I have this link:
<a id="hrefPdf" runat="server" href="#" target="_blank"><asp:Literal ID="PdfName" runat="server"></asp:Literal></a>
In my code behind I have this on the onload event:
Stream pdf= getPdf
if (pdf != null)
{
SetLinkPDF(pdf);
}
private void SetLinkPDF(IFile pdf)
{
hrefPdf.href = "MyPDF to the Browser"
PdfName.Text = pdf.PdfName;
}
Someway I have to process the stream pdf (IFile contains Name, Stream,Metadata, etc of the PDF)
What can I do to proccess this and whe I click show the stream at a new browser?
I have another probelm, is not working the OnClientClick="aspnetForm.target='_blank';" timbck2 suggested me. I have to open the file (image or pdf ) in a new window, what could I do? Is not working this. Thank!
Timbbck2 my asp code is:
<asp:LinkButton runat="server" ID="LinkButtonFile" OnClick="LinkButtonFile_Click" OnClientClick="aspnetForm.target = '_blank';"></asp:LinkButton>
Thanks!!!
I've done this from a file on disk - sending the data from a memory stream shouldn't be that much different. You need to supply two pieces of metadata to the browser, in addition to the data itself. First you need to supply the MIME type of the data (in your case it would be application/pdf), then the size of the data in bytes (integer) in a Content-Length header, then send the data itself.
So in summary (taking into account the comments and what I think you're asking, your markup would look like this:
<asp:LinkButton ID="whatever" runat="server" OnClick="lnkButton_Click"
OnClientClick="aspnetForm.target='_blank';">your link text</aspnet:LinkButton>
These few lines of C# code in your code behind should do the trick (more or less):
protected void lnkButton_Click(object sender, EventArgs e)
{
Response.ClearContent();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "inline; filename=" + docName);
Response.AddHeader("Content-Length", docSize.ToString());
Response.BinaryWrite((byte[])docStream);
Response.End();
}
To display pdf directly in the browser you should set content type for the response to application/pdf
Your user should also have some kind of pdf reader installed for this to work.
Did you try Response.BinaryWrite?? You probably want to set some headers as well.
The top answer suggests converting (casting) a stream to a byte[] first, that will download the file to the server (from whatever stream it is coming from) and then send it to the client.
If you need to provide a Stream as a parameter for some external service (like me for Azure Storage) you can use the following method.
public ActionResult Coupons(string file)
{
Response.AddHeader("Content-Disposition", "inline; filename=" + file);
Response.ContentType = "application/pdf";
AzureStorage.DownloadFile(file, Response.OutputStream);//second parameters asks for a 'Stream', you can use whatever stream you want here, just put it in the Response.OutputStream
return new EmptyResult();
}
That will Stream the file to the client directly (as far as I know).

IE9 randomly popping Windows Security Dialog when I send down a binary blob as a .xlsx

So on our website, we have multiple reports that can be downloaded as an Excel Spreadsheet, we accomplish this by reading in a blank template file from the harddrive, copying it into a MemoryStream, pushing the data into the template with DocumentFormat.OpenXml.Spreadsheet; Then we pass the MemoryStream to a function that sets the headers and copies the stream into the Response.
Works GREAT in FF & Chrome, but IE9 (and 8, so my QA tells me) randomly pop a Windows Security login dialog asking you to log into the remote server. I can either cancel the dialog, or hit ok (the credentials seem to be ignored), and get the Excel file as expected. Looking at the queries (using CharlesProxy) I cannot get the login dialog to pop until I disable CharlesProxy again, so I cannot see if there's any difference in the traffic between my dev machine and the server. It also doesn't happen when running debug from my local-host, just from the Dev/Test server.
Any help would be useful, the code in question follows. This is called out of a server-side function in the code behind, hence the RespondAsExcel clears the response and puts in the xlsx instead.
using (MemoryStream excelStream = new MemoryStream())
{
using (FileStream template = new FileStream(Server.MapPath(#"Reports\AlignedTemplateRII.xlsx"), FileMode.Open, FileAccess.Read))
{
Master.CopyStream(template, excelStream);
}
//Logic here to push data into the Memory stream using DocumentFormat.OpenXml.Spreadsheet;
Master.RespondAsExcel(excelStream, pgmName);
}
public void RespondAsExcel(MemoryStream excelStream, string fileName)
{
var contenttype = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.Clear();
Response.ContentType = contenttype;
fileName = Utils.ReplaceWhiteSpaceWithUnderScores(fileName);
Response.AddHeader("content-disposition", "inline;filename=" + fileName);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.BinaryWrite(excelStream.ToArray());
//If that doesn't work, can try this way:
//excelStream.WriteTo(Response.OutputStream);
Response.End();
}
public void CopyStream(Stream source, Stream destination)
{
byte[] buffer = new byte[32768];
int bytesRead;
do
{
bytesRead = source.Read(buffer, 0, buffer.Length);
destination.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
}
A couple of ideas come to mind regarding that "extra authentication dialog" that can always be dismissed...won't promise this is your issue, but it sure smells like a first-cousin of it.
Office 2007 and later documents open HTTP-based repositories with the WebClient libraries, which do not honor any of IE's security zone filters when requests are made. If the file is requested by IE, and host URL contains dots (implying a FQDN), even if the site is anonymously authenticated (requiring no credentials), you'll get the "credential" dialog that can be cancelled or simply clicked three times and discarded. I was dealing with this problem just yesterday, and as best I can tell, there's no workaround if the file is delivered with IE. There's some quirk about how IE delivers the file that makes Office apps believe it has to authenticate the request before opening it, even though the file has already been delivered to the client!
The dialog issue may be overcome if the document is delivered from a host server in the same domain as the requesting server, eg some-server.a.domain.com to my-machine.a.domain.com.
The second idea is something strictly born of my own experience - that the openoffice vendor format types sometimes introduce their own set of oddness in document stream situations. We've just used a type of application/vnd.ms-excel and, while it seems it should map to the same applications, the problems don't seem to be as prevalent.
Perhaps that can give you some thoughts on going forward. Ultimately, right now, I don't think there's an ideal solution for the situation you're encountering. We're in the same boat, and had to tell our in-house clients that get the dialog to just hit "Cancel," and they get the document they want.
In your RespondAsExcel() method, change your content-dispositon response header from inline to attachment. This will force the browser to open the file as read only. See KB899927.
Response.AddHeader("content-disposition", "attachment;filename=" + fileName);
I had something similar with VBScript when using "Response.ContentType="application/vnd.ms-excel". I simply added the following code and the Windows Security popup window no longer appeared:
Response.AddHeader "content-disposition","attachment; filename=your_file_name_here.xls"

itextsharp open pdf with another browser windows

basically below is the code for me to read pdf file, the output for this code below is ask client to download the pdf file and open it from client side, this is not what i want,what i want it open the pdf at another browswer windows or open in inside tag under same browser windows, but how can i make it?
var fi = new FileInfo(Server.MapPath(#"~/AIA2.pdf"));
Response.Clear();
Response.AddHeader("Content-Disposition",
String.Format("attachment; filename=\"{0}\"",
"AIA2.pdf"));
Response.AddHeader("Content-Length", fi.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.WriteFile(fi.FullName);
Response.End();
This is not upto the server to decide how content is handled - content disposition could be set to attachment or inline but its to the handling application to process these and i do not think any browser does that.
I can suggest a two step solution for this:
Use inline; instead of attachment
On the client side (if you have control on that ofcourse), use something like
That should do the trick!

How do I print an existing PDF from a code-behind page?

I've seen a few questions like this around SO but couldn't find anything that's right for me. The chain of events that I would like to occur is as follows:
User clicks an ASP.NET button control
This fires that button's onclick event, which is a function foo() in the C# codebehind
foo() calls some other (unimportant) function which creates a PDF which ends up saved to the server's disk. That function returns the path to the PDF
Without any other user interaction, once the PDF is generated, the print dialog box opens in the user's browser to print that PDF
What do I need to do to accomplish step 4? Ideally, it would be something I can call in foo(), passing in the path to the PDF, that will trigger the print dialog box in the user's browser (printing the PDF and not the page the from which the onclick fired).
I think that I might be able to forward to the URL of the PDF document, and embed some Javascript in the PDF that automatically prints it, but I would rather not - I don't necessarily want to print the PDF every time it's opened (in a browser). Any other good way to do this?
Response.Clear()
Response.AddHeader("Content-Disposition", "attachment; filename=myfilename.pdf")
Response.ContentType = "application/pdf"
Response.BinaryWrite(ms.ToArray())
Where ms = a memorystream containing your file (you don't have to write it to disk in-between.)
Otherwise if you absolutely have to deal with coming from the hard disk, use:
Response.WriteFile("c:\pathtofile.pdf")
Thanks for the answer Vdex. Here is the iText/C# version.
PdfAction action = new PdfAction();
action.Put(new PdfName("Type"), new PdfName("Action"));
action.Put(new PdfName("S"), new PdfName("Named"));
action.Put(new PdfName("N"), new PdfName("Print"));
PdfReader reader = new PdfReader(ReportFile.FullFilePath(reportFile.FilePath));
PdfStamper stamper = new PdfStamper(reader, Response.OutputStream);
stamper.Writer.CloseStream = false;
stamper.Writer.SetOpenAction(action);
stamper.Close();
I did not try this, but it is an idea:
If you can read querystring parameters in javascript embedded in the PDF, then embed the javascript, and make the print function be conditional on a javascript parameter.
That way, if you redirect to, for instance, yourpdf.pdf?print, it will print, and if it is opened without the print parameter, it behaves as any other normal PDF would do.
If you want to go down the path of printing it as soon as it is opened:
There is a flag that you can insert into the PDF that forces it to open up the print dialog as soon as the PDF is opened. I did this ages ago using the abcpdf component in classic ASP, the code looked something like:
Set oDoc = Server.CreateObject("ABCpdf4.Doc")
oDoc.SetInfo oDoc.Root, "/OpenAction", "<< /Type /Action /S /Named /N /Print >>"
Obviously the code would look different depending on which PDF creation tool you are using...
The solution I arrived at was this:
Create a new ASP.NET web form (I called mine BinaryData.aspx) to serve as a placeholder for the PDF. In the code behind, the only method should be Page_Load, which looks like:
protected void Page_Load(object sender, System.EventArgs e)
{
//Set the appropriate ContentType.
Response.ContentType = "Application/pdf";
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Cache-Control", "no-cache");
//Get the physical path to the file.
string FilePath = (string)Session["fileLocation"];
if ( FilePath != null )
{
string FileName = Path.GetFileName(FilePath);
Response.AppendHeader("Content-Disposition", "attachment; filename="+FileName);
//Write the file directly to the HTTP content output stream.
Response.WriteFile(FilePath);
Response.End();
}
}
The PDF is passed in to the page through the Session variable named "fileLocation". So, all I have to is set that variable, and then call Response.Redirect("BinaryData.aspx").
It doesn't automatically print, but it triggers the download of the PDF without leaving the current page (which is good enough for me).

Categories

Resources