1

I am generating a Pdf using ItextSharp using html to pdf. I want to display a preview of the Pdf on the screen so the user can see it. The user will be able to play around with the html and get the desired resulting pdf. I am generating the pdf correctly but am having trouble displaying it on the screen.

Ajax call:

 function Preview() 
 {
    var HtmlInfo = document.getElementById('HtmlToBarCodes').value;

    $.ajax({
        url: '/BarCodeGenerator/PreviewPDF',
        type: 'POST',
        cache: false,
        data: { Html: HtmlInfo },
        success: function (data) {
            Loading = false;

            $("#pdfResult").html(
                $('<iframe>', {
                    src: data,
                    width: '600px',
                    height: "800px"
                }));
        },
        error: function (x) {
            Loading = false;
        }
    });
}

Controller

[HttpPost]
[ValidateInput(false)]
public FilePathResult PreviewPDF(string Html)
{
        FileStream fs = null;
        string pdfFilePath = "";

        try
        {
            //ItextSharp, Html -> Pdf
            pdfFilePath = BLL.GenerateBarCodes.GenerateBarcodes(Html, 5);

            Response.ClearHeaders();
            Response.ClearContent();
            Response.Buffer = true;

            Response.AppendHeader("Content-Disposition", "inline; attachment; filename=Preview.pdf");
            Response.ContentType = "application/pdf";

            Response.WriteFile(pdfFilePath);

            Response.Flush();
            Response.End();


            //fs = new FileStream(pdfFilePath, FileMode.Open, FileAccess.Read);


        }
        catch (Exception ex)
        {
            //ToDo: log error
        }

        return File(pdfFilePath, "application/pdf", "Preview.pdf");
    }

I can confirm that the Pdf is generating and saving on my end in my C:Temp folder and I can view it as well, but when I click preview all i get is a blank. I am not sure how to load the pdf data from the ajax call or if it is even possible.

  • Take a look at http://stackoverflow.com/questions/9821856/how-can-i-call-an-mvc-filecontentresult-by-jquery-and-get-it-to-prompt-the-user – Shyju Sep 13 '16 at 14:37
  • I don't want to download the pdf, I just want to preview the pdf – CSharpGood_VBSucks Sep 13 '16 at 14:41
  • The ` – spender Sep 13 '16 at 14:42
  • Also change `Response.AppendHeader("Content-Disposition", "inline; attachment; filename=Preview.pdf");` to `Response.AppendHeader("Content-Disposition", "inline;filename=Preview.pdf");` as inline is to render and attachment is to prompt for download. For browser settings see my answer here - http://stackoverflow.com/questions/37906586/httpresponsemessage-returning-bytearraycontent-result-preview-document-in-chro/37914380#37914380 – Ravi A. Sep 13 '16 at 14:48
  • Thanks you all for helping – CSharpGood_VBSucks Sep 26 '16 at 14:29

2 Answers2

0

The iframe src attribute expects a URI, not the raw data that populates the iframe.

You have 2 options.

a) use the srcdoc attribute (if you only need to support recent browsers).

b) construct a data URI from the data and use it as src

Below is a demo outlining both approaches

var data = "<html><body>hello world</body></html>"
$(function() {
  $("#target").append($("<iframe>", {
    srcdoc: data
  }));
  var dataUri = "data:text/html;base64," + btoa(data);
  $("#target").append($("<iframe>", {
    src: dataUri
  }));

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js">
</script>
<div id=target></div>

Edit:

Of course, pdf is a binary format. You can download as a blob, make a data URI and win!

$(function() {
    var oReq = new XMLHttpRequest();
    oReq.open("GET", "/somedoc.pdf", true);
    oReq.responseType = "blob";
    oReq.onload = function (oEvent) {
        var blob = oReq.response;
        var url = URL.createObjectURL(blob);
        $("#target").append($("<iframe>", { src: url }));
    };

    oReq.send();
})
spender
  • 106,080
  • 28
  • 202
  • 324
  • when I do srcdoc: data, I just get the raw data, but when i do src: "data:application/pdf;base64," + btoa(unescape(encodeURIComponent(data))), I just get a blank 2 page pdf no matter how many pages the pdf I have is – CSharpGood_VBSucks Sep 13 '16 at 15:54
  • @CSharpGood_VBSucks : q1) Is the data actual text or is it binary? q2) `unescape(encodeURIComponent(data))`... what's all this about? – spender Sep 13 '16 at 15:57
  • It's binary and the unescape(encodeURIComponent(data)) is because i got the error Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range and went to Stackoverflow: answer – CSharpGood_VBSucks Sep 13 '16 at 15:59
  • @CSharpGood_VBSucks : See my edit for dealing with binary download. – spender Sep 13 '16 at 16:13
0

There are many solutions and workarounds.I will point out two solid solutions.

solution 1:

step 1: generate pdf in back end and save it in server location. That pdf could be able to access via URL.

step 2:pass that URL as a response for AJAX call.

step 3:get the ajax response and set to iframe and show iframe there are lot of ways to preview pdf in this SO answer.

references :

Recommended way to embed PDF in HTML?

Display PDF using an AJAX call

You can show your pdf using bellow jquery code

var iframe = $('<iframe>');
iframe.attr('src','http://www.pdf995.com/samples/pdf.pdf');
$('#targetDiv').append(iframe);

solution 2: use a tag. Please go through this article.

You don't necessarily need Ajax for this. Just an link is enough if you set the content-disposition to attachment in the server side code. This way the parent page will just stay open, if that was your major concern (why would you unnecessarily have chosen Ajax for this otherwise?). Besides, there is no way to handle this nicely acynchronously. PDF is not character data. It's binary data. You can't do stuff like $(element).load(). You want to use completely new request for this. For that pdf is perfectly suitable.

reference :
Download and open pdf file using Ajax

Community
  • 1
  • 1
Sanka
  • 1,104
  • 1
  • 10
  • 18