Rendering PDF using object/embed/iframe is not working properly - html

I am trying to display PDF for preview using object/embed/iframe html tags, but its not working as expected.
Can someone point out what is going wrong here?
Here is my bit of code:
In HTML _PDFPreview.cshtml:
#model byte[]
<div style="width: 875px;">
<object id="previewPdf" data="data:application/pdf;base64,#Convert.ToBase64String(Model)" style="overflow: visible;"/>
</div>
In Controller action:
public ActionResult SomeActionMethod()
{
// some logic to get pdfResult object
return View("~/View/_PDFPreview.cshtml", pdfResult.BuildPdf(ControllerContext));
}
Note: I am using Rotativa NuGet package for generating the PDF. The action method returns view with proper data. But in browser it ends up in getting blank screen.
Test Case: On changing object tag to iFrame it works in Chrome but not in FireFox.
I will appreciate any kind of relevant suggestions.
Thanks in Advance.

Got the fix!
"Test Case: On changing object tag to iFrame it works in Chrome but not in FireFox."
My bad. It was due the FF browser setting that was directly downloading the file instead of previewing. On changing the setting the issue got fixed.
Thanks.

Related

Rendering a pdf file from an html view to display it on a web page as a image preview

I need to create a pdf preview that should be displayed on a web page as an image. The pdf file is just a simple report build on almost plain HTML. Essentially I had a problem with displaying checkboxes, now I replaced them with pics of checkboxes but the issue remains the same.
Here how I create the pdf report from my HTML view with help of groovy and grails:
def html = htmlRenderService.getReport(info)
ByteArrayOutputStream out = new ByteArrayOutputStream()
HtmlImageGenerator htmlImageGenerator = new HtmlImageGenerator()
htmlImageGenerator.loadHtml(html)
BufferedImage bi = htmlImageGenerator.bufferedImage
ImageIO.write(bi, "PNG", out)
byte[] bytes = out.toByteArray()
String base64bytes = encoder.encodeToString(bytes)
String src = "data:image/png;base64," + base64bytes
out.flush()
def getReport(Info info) {
return groovyPageRenderer.render(view: REPORT_VIEW,
model: [info: info])
}
Then I send the src string to my view and render it as:<img src="${src}" alt=""/>
Then my checkbox pic looks like this: <div style="/*style stuff*/ background-image: url(data:image/png;base64,LINK_TO_THE_IMAGE"></div>
In the end, I received a picture of my pdf report rendered pretty well displaying as an image on my page, BUT without checkboxes. Here is the picture of one part of it:
And here is the same part but from the pdf document which I rendered all the same way, but just downloaded directed from my webapp:
Here is an example where I combined both options(input checkbox and image checkbox) and rendered it as an image:
So what could cause this issue? Thank you in advance.
UPDATE: I came across today to this comment under another issue with HtmlImageGenerator:
HtmlImageGenerator seems to use a JEditorPane for rendering the HTML. Swing HTML support does not extend to the ability to render data images. It might be possible by digging into the HTMLEditorKit and changing the image loading element to support data images, but then you'd need to find a way to get HtmlImageGenerator to use the altered editor pane.
Seems that HtmlImageGenerator doesn't work well with images inside HTML files, but it's still unclear why it doesn't render checkbox inputs as well.
Without seeing the code you end up with after page load, check the chrome dev tools panel to see if the image has actually loaded correctly to the page which will tell you it's at least accessible to use. Then check if the url is output correctly to the div as the background-image. If it looks correct and there aren't related errors in the console, it is likely a css setting.
With background images, your container will need to contain content or else you will need to specify:
width
height
a display setting
background-position, and a
background-size
If you can upload more info, I might be able to be more specific.

VueJS SPA not loading properly on Microsoft Edge

For some reason, content is not being displayed on the website if viewed from the microsoft edge browser. The background is loaded, which is loaded through HTML, but the parts loaded with Vue do not get displayed and i dont understand why.
I have no idea where to start to debug this.
<div class="nk-main">
<router-view :key="$route.fullPath"></router-view>
</div>
In the console, i get these errors on Microsoft Edge:
https://imgur.com/a/y7V3NG7
$store is the VueX variable. And the this error I dont understand.
Does anyone have any idea how I can fix this or how I can further debug the issue?
I think #birdspider answered your question. In your Vue.js templates you referencing to Vuex store like this this.$store.state.blabla instead of $store.state.blabla. This happen because this keyword in template is undefined. When you access your variables in template you have to dont use like {{this.variable}}, just {{variable}}, declared in data() setction.

htmlRenderer.PDFSharp not converting labels

I am trying to get familiar with htmlRenderer.pdfsharp and have come across an issue that I am trying to figure out. It is not rendering the following HTML:
<td><label for=\"Date\">Date</label></td>
The code I am using to generate the PDF is from one of their examples but it is as follows:
PdfDocument pdf = PdfGenerator.GeneratePdf(html, PageSize.Letter);
The rest of the HTML is populating just fine and am not sure where to go from here with the HTML Renderer. Anyone else ran into this issue and have a fix?
Edit: I removed calling it PDFSharp's html render and linked to the nuget package I am using for htmlRender.pdfsharp.

How can I embed a PDF document in a KnockoutJS template without PDF plugins issuing warnings?

I am trying to embed a PDF document in an HTML view, with a Knockout ViewModel providing the URL for the document. I believe that the correct HTML element for this is <object>, so I have the following view:
<div class="documentviewerpdf">
<object data-docType="pdf" data-bind="attr: { 'data': EmbedPDFLink }" type="application/pdf" width="100%" />
</div>
and the following as a view model:
function AppViewModel() {
this.EmbedPDFLink = "http://acroeng.adobe.com/Test_Files/browser_tests/embedded/simple5.pdf";
}
ko.applyBindings(new AppViewModel());
jsFiddle
This displays the PDF in Chrome, Chrome Canary (both using native Chrome PDF plugin), and Firefox 27 (Adobe Reader XI plugin), however all three browsers display a warning in a bar across the top of the screen. Chrome's is yellow and states that it Could not load Chrome PDF Viewer, while Firefox's is grey with an information icon and states that this PDF document might not be displayed correctly. The same code loads the plugin empty on IE9.
If I replace the data-bind attribute with a direct data attribute containing the hard coded URL for the PDF document, Chrome and Firefox display correctly, while IE9 displays nothing at all, not even the empty plugin.
I have tried setting the data attribute using a <param> element within the <object> as well, and that did not work at all in any of these browsers.
I have also tried using an <embed> tag, which gives similar results though works in IE9, however this does not seem like it is semantically correct. However, the embed element documentation states that any attributes are passed to the plugin - given that the elements are so similar, is it likely that the data-bind attribute is being passed to the PDF plugins, and causing this problem?
It appears that the only difference in mark-up between the hardcoded and data-bind versions is the presence of a data-bind attribute on the latter, so I think that is causing the problem with the plugins, as the data URL attribute is being set correctly.
Is there a way to set the data attribute on the object using Knockout, without leaving a data-bind attribute there as well? Is there another way that anyone knows to avoid this issue?
I'm not 100% sure, but I think this is what's happening.
Your html markup has an <object data-docType='pdf' /> - so that is there immediately upon DOM load. However, the data attribute of it is using a KO binding. So immediately upon DOM load when the <object> html element is loaded, the KO bindings aren't applied just yet and you get the error.
I tested it out, and I constructed the <object> html markup in Javascript and then added it to the DOM and the error went away. Hope it helps, see fiddle
function AppViewModel() {
this.EmbedPDFLink = "http://acroeng.adobe.com/Test_Files/browser_tests/embedded/simple5.pdf";
this.addPdf = function () {
var html = "<object data-docType=\"pdf\" data=\"" + this.EmbedPDFLink + "\" type=\"application/pdf\" width=\"100%\" />";
$('.documentviewerpdf').append(html);
};
}
ko.applyBindings(new AppViewModel());
and the HTML
<button data-bind="click: addPdf">Load PDF</button>
<div class="documentviewerpdf"></div>
Edit
Here's an updated fiddle that will automatically load the PDF when you get to the page (more in line with what you want your end result to be, I think). I tested it in IE, FIrefox, and Chrome (latest versions) and received no errors.
Fiddle
Use bindings to keep all of your attributes hidden until the source path has been evaluated. The plugin sees your other attributes and thinks you have a bad element.
data-bind="attr: { 'each-attribute-here': true }"
http://jsfiddle.net/C8txY/8/
Chrome recognizes your PDF too quickly, before the value is evaluated. Tie all of the properties that the plugin is looking for into your binding.
You could also use a custom binding here to add the attributes and pass in the value of the location of the PDF. This custom binding handler should not directly inject HTML into the DOM.

Excel file downloads instead of displaying in iframe

I have this in my controller class:
public ActionResult ExcelDoc()
{
var doc = Server.MapPath("~/Content/Sheet1.xlsx");
return File(doc, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
}
And in my view:
<iframe src="/Centres/ExcelDoc"></iframe>
It simply DOES NOT display the file in the iframe. Instead, it begins downloading sheet1.xlsx as ExcelDoc.xlsx. Very frustrating as previous questions have helped me to develop this solution to my previous problem of trying to display a dynamically generated excel file in an iframe. I am using Google Chrome, if that is relevant.
Returning a file makes your browser try to download it, that's expected behaviour. I think it's not possible to display an excel file as-is in your browser window, unless you use something like a plug-in.