Control display of streamed PDF in browser - c#

Using info found here and elsewhere I have successfully implemented an app that will pull a PDF from our document storage server, stream it across our firewall and display it in a frame on the client's web browser. The PDF is loaded into a page using the following code and that page is the source for the iframe.
int ImageID;
if (int.TryParse(Request.QueryString["ImageID"], out ImageID))
{
FileTransferService.FileTransferClient client = new FileTransferService.FileTransferClient();
Byte[] documentStream = client.GetFile(Classes.AppSettings.pwServer, Classes.AppSettings.pwDatabase, Classes.AppSettings.pwUsername, Classes.AppSettings.pwPassword, Classes.AppSettings.pwCabinet, ImageID, "", "");
Response.ContentType = "application/pdf";
Response.BinaryWrite(documentStream);
}
This is working fine most of the time, but due to settings on the client for the Acrobat Reader plugin the PDF will sometimes open in Acrobat Reader rather than displaying in the web page, leaving our page with an empty hole where the PDF should be. I've searched for a third party PDF viewer we could use in the app without success. Either they don't accept a stream as a source or the image quality is unacceptable. If we could force it to always pop up in Acrobat Reader that would be acceptable, but we'd prefer it to be displayed in the web page. For security reasons we don't want to write the file to disk and display it from there.
Is there a method to force the viewing behavior one way or another or a third party viewer we could use that will solve this problem?

As an alternative to the optimal solution, you could add the 'Content-Disposition' header to make the browser always treat it as a download.
Usage:
Content-Disposition: attachment; filename="example.pdf"
This may also be worth looking into, although I've never used it:
System.Net.Mime.ContentDisposition
Represents a MIME protocol Content-Disposition header.

Related

How to directly print a PDF dynamically created with iTextSharp using asp.net c#?

I have looked around a lot and i cant seem to find a way that works for me. I am creating a website, and I have two buttons, a Download button (which works fine) and a Print button that should print the PDF (or even just open the PDF in adobe with the print dialog open).
The biggest difference between my question and many others is that I'm not trying to create a new document. My PDF is generated using a template PDF that I have created already.
I just need a way to print the document. I cannot save it on the server because I want the client to be able to print it. I have tried a MemoryStream, but its not working(granted I probably didnt write it correctly, the code is below). The header is grabbed from a different page.
using (var ms = new MemoryStream())
{
Response.ContentType = "application/octet-stream";
Response.AppendHeader("Content-Disposition", header); /
Response.Buffer = true;
Response.Clear();
var bytes = ms.ToArray();
PdfReader r = new PdfReader(template);
using (PdfStamper ps = new PdfStamper(r, Response.OutputStream))
{
AcroFields af = ps.AcroFields;
...
ps.FormFlattening = true;
}
Response.OutputStream.Write(bytes, 0, bytes.Length);
Response.OutputStream.Flush();
Again, I want to be able to have the client print this PDF that is generated once they click the Print button.
Before going down this path too far I just want to make sure that some things are properly explained. I don't know your level of expertise so please don't be offended if I say something that is obvious.
First, you say that you have two buttons, "Download" and "Print". We know what you intend for these to do however its important to know and understand that both of these options are "download". Your "Download" button is really "download and (maybe) prompt to save" and your "Print" button is really "download and then if the person has a PDF renderer configured in their browser (which most modern browsers have) then render the PDF otherwise prompt to save". This might be very obvious already to you but I just wanted to make sure it was clear. I personally don't have a PDF renderer bound to my default browser so all PDFs download for me every time.
Second, the server gets to send one and only one "thing" back to the client in response to a request. That "thing" can have meta data (headers) associated with it but there are very few standard meta keys out there that are relevant. One key (content-disposition) is whether this response should be treated, relative to the initiating request, as "inline" or an "attachment". Some browsers treat the latter as a "download and (maybe) prompt to save" but some still will launch an associated application. There's another key (mime type of application/octet-stream) that some people use to further trick browsers that essentially says "seriously dude, this thing I'm sending is so weird that it would be impossible for you to figure it out so just save it to disk".
This is all very important because there's no "please print this" thing that you can send from the server that's in any standard spec (or any spec that I've ever seen for that matter). Also, the server cannot even say "open this in a new tab or browser window". Both print and window/tab control are client-side features so you need to attack from that angle.
So now on to some options. These options all assume that your clients have modern browsers with PDF renderers built-in and enabled.
One option that you could use would be to wrap your PDF in an iframe that has some JavaScript that calls window.print() upon loading. Google used to (and maybe still does) for their calendar. You'll need to test this with your various client rendering devices to make sure it works as you expect.
Another option is to try using PDFObject to embed the PDF and then use the same JavaScript mentioned above.
One last option is to slightly change your PDF generation code and add JavaScript to your PDF the tries to print the PDF on load. JavaScript support in PDF renderers isn't universal so you'll need to check whether this works with your clients. Also, this setting is "baked" into the PDF that you make, so if someone saves it to disk, every time they open it it will try to print which is very annoying.

Generating pdf using generic handler (ashx)

I got a requirement to create pdf on the fly from the data stored in database.
I am using html, jquery and WCF in my application.
I don't find a way to generate pdf (Show in a browser or as an attachment) using client technology (jquery, or any other client plugins). I tried to use pdf.js, but could not able to succeed. Later I used .net generic handler to generate pdf. I was passing bytearray to handler, in turn pdf started rendering on client.
I got some random issue, then I wrote a sample application to make sure handler is working fine. I used same code with a static text to generate pdf, but it started throwing a error on the client.
Below is the code snippet I used
context.Response.Clear();
context.Response.ContentType = "application/pdf";
context.Response.AddHeader("content-disposition", "inline; filename=download");
context.Response.Write("Hello World");
//context.Response.BinaryWrite(System.Text.Encoding.Default.GetBytes("Hello world"));
//context.Response.BinaryWrite(System.Text.Encoding.UTF8.GetBytes("Hello world"));
context.Response.Flush();
context.Response.End();
I am getting errors on all the browsers
Failed to load pdf document on Chrome.
An error occurred while loading the PDF. PDF.js v0.8.505 (build: da1c944) Message: InvalidPDFException - In mozilla firefox
File does not begin with '%PDF-' in IE.
Note: I tried with aspx page too. I cant create physical file due security issues. If there is any better way of achieving it please let me know. Thanks in advance.
PDF is a standard file format.You cannot write a normal text file and rename it to filename.pdf and wish it to work.
You will need .Net libraries for that.There are lot try googling .Net pdf library
Some Info.
pdf.js is just for viewing in browser.
setting context.Response.ContentType just tells the browser the file its gonna receive,So it can use existing mapped application to open it.Like Adobe browser plugin for pdf file.

How should I be saving .doc documents to a SQL Server database

I am saving a .doc file to a SQL Server database as varbinary(max) using the C# code below.
I am able to save the file, but when I retrieve the file back and want to display the contents on the web page, my code is downloading the file and I am in great confusion about how to handle it.
The exact functionality I am looking for is the way naukri.com uploads the resume and gives a preview of it. My code is :
byte[] fileContent = new byte[fuResume.PostedFile.ContentLength];
fuResume.PostedFile.InputStream.Read(fileContent, 0, fuResume.PostedFile.ContentLength);
//lblAppliedMessage.Text = ByteArrayToString(fileContent);
//lblAppliedMessage.Text = BitConverter.ToString(fileContent).Replace("-", string.Empty);
byte[] btYourDoc;
btYourDoc = fileContent;
Response.ContentType = "application/ms-word";
Response.AddHeader("Content-Disposition", "inline;filename=yourfilename.doc");
Response.OutputStream.Write(btYourDoc, 0, fileContent.Length);
Response.BinaryWrite(btYourDoc);
Response.End();
The reason your file is getting downloaded instead of displayed is because you're setting the content type to application/ms-word. This tells a browser to download the file (they can't natively handle files of that type so they delegate to an external app).
You'll need to have code that knows how to interpret the MS Word format and convert that to something viewable in a browser (HTML, some kind of plugin that will do that for you, etc). Saving the raw Word document and then sending it back to the client in the same state is basically just having them download a Word file.
squillman is right. There are tons of third party components that do Word -> HTML conversion.
One other option, which may be more appropriate for an intranet site, is to install Word on the server.
An example of this is here:
http://www.c-sharpcorner.com/UploadFile/munnamax/WordToHtml03252007065157AM/WordToHtml.aspx
Effectively, the doc is opened, saved out as HTML, then subsequent requests can retrieve the HTML version of the file for preview.
Office automation server side has many pitfalls, however - see http://support.microsoft.com/kb/257757 for more information.
Here's a good one where the end result it's up to the user whether to download or view the file here's the link but #Squillman is right by putting the Response headers you're telling it to download.

How to Open MemoryStream File In Browser?

I want to create a Text file in my code behind file in my web application. However, I am not allowed to save this file to server. So I tried to use MemoryStream class to save my file into memory. So far I have,
MemoryStream memoryStream = new MemoryStream();
TextWriter textWriter = new StreamWriter(memoryStream);
textWriter.WriteLine("Something");
memoryStream.Close();
It seems like working but my requirement is to open this file on client browser when he/she clicks button. Since this file does not have a physical path like ..../text.txt. I have no idea how to open it on browser.
How can I do this in ASP.Net using C#. I searched a lot but could not find a solution working for me.
Thanks in advance.
This is a lot easier than you think. Keep in mind that the HTTP protocol doesn't actually transfer "files" in the strictest sense of the word. It transfers requests and responses, each containing headers and content. In this case, you're concerned with the headers and content of the response.
The easiest way to do this in a WebForms application is with a generic handler. Specifically, take a look at the implementation of the handler's response in that link:
context.Response.ContentType = "image/png";
context.Response.WriteFile("~/Flower1.png");
This is writing the content of an image file to the response after setting the response's header appropriately. What you want is closer to what's commented out in the implementation:
context.Response.ContentType = "text/plain";
context.Response.Write("Hello World");
This would send to the browser plain text, nothing more. The browser won't think it's a web page or anything like that, won't apply any styles to it, etc. As far as the web browser is concerned, it just downloaded a text file with the words "Hello World" in it. You can Response.Write() all the text you want to build that file.
You can further customize your response headers to give the browser even more information. For example, if you add the following header to your HttpResponse:
Content-Disposition: attachment; filename=myfile.txt
Then the browser will translate that to mean that this "file" should be downloaded and saved, not just displayed. (Of course, the user's browser settings may tell it to display it anyway, but this is the proper way for the server to "suggest" to the browser that it should save the file.)
From the point of view of the browser, it doesn't matter where the "file" came from. Whether it was from the server's file system or dynamically generated or magically conjured, it makes no difference. The browser is concerned only with the response headers and content. If the headers say it's text, and they say that it's a file, then the content will be treated as a text file.
Why do you need to write a MemoryStream? Just write it to the HTTP response if you want to send it to the browser.
Response.WriteLine("Something");
If you want to make the browser download this response as a file, see here.
I honestly believe this isn't a good pattern in Web development.
It's just about reading your file and send its data as text to the client-side (Web browser), edit it in a textbox, send back modified text and save it as file in the path or storage of your choice.
HTTP is an stateless protocol, so you won't be leaving a file opened in the server-side while its contents are edited in client-side, as both tiers are absolutely disconnected after server response ends.
Ok, I think I figured out what you want. You say you have a button, with witch you want to go to the content of a text-file, that you want to create in-memory, but you don't know what url to send the browser to when the user clicks the button?
If this is the case here's what you can do:
1) On the page that has the button, set the href (or link-location or whatever) of the button to be a new asp.net page (jet to be created). Something like "textfile.aspx" or whatever. Also, remove all the code regarding the memory-stream.
2) Create the new asp.net file (textfile.aspx, or whatever you decided to call it). The content of that file should be like this:
Response.WriteLine("Something"); // Or whatever you previously wrote to the MemoryStream
The point is, you should separate into two different files (or separate action based on query-string).

Set the source of Adobe PDF browser plugin to be a byte stream?

Is it possible to have the source for an Adobe Plugin to be a PDF byte stream?
If so, how would this be declared in markup?
EDIT 1:
OK, so let me elaborate on this. I have built a site that runs on Azure. The site's back-end is a WCF web service, also on Azure.
One particular functionality of the site has to do with reporting. Once the user selects the type of report they want, a request is made to the service and a byte stream of a pdf file is sent back as a response.
Now, the question is how would the user view the file? Is it possible to set the Adobe Acrobat PDF plugin's document source to be something along the lines of:
<OBJECT>
<PARAM src="asdfkjaskflasjdlfkjasd"/> //byte stream
<PARAM mimeType="application/pdf;"/> //stream's mime type
</OBJECT>
EDIT 2:
OK, so no-one wants to take a crack at this. However, the only reason I am asking is because it is entirely possible to set the source of an image with the following code:
<img class="myImage" img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAA"/>
where everything past the image/png;base64 represents the byte content of the image encoded as a base64 string.
So is it still possible?
Thanks,
I doubt the Adobe plugin can be made to fetch PDF data from a data: URL.
And even if it is possible in some browsers, you will with 100% certainty not be able to achieve a cross-browser solution this way: data: URLs don't work in IE < 8 at all, and are limited to 32 kilobytes' size 8 and 9.
What speaks against simply serving the byte stream in a separate resource with a PDF content-type?

Categories