0

The code below works perfectly in my local environment..however, the same code online does not work. I receive no error whatsoever, the iFrame just doesn't popup as expected.

The src attribute is always changed in the iframe as expected...

if($('#iFramePdf').length > 0)
    $('#iFramePdf').attr('src', json.pdf);
else
    $('body').append('<iframe class="hidden" id="iFramePdf" src="' + json.pdf + '"></iframe>');

// enough time for the src being changed
setTimeout(function()
{
    $('#iFramePdf').get(0).focus();
    $('#iFramePdf').get(0).contentWindow.print();
}, 1000);

What can be wrong?

Edit 1: This seems that the problem might be due to content-type headers? the json.pdf has the absolute url like so:

http://mywebsite.com/public/files/somefile.pdf 

And it doesn't open the chrome preview dialog. But if I remove http://mywebsite.com and send only public/files/somefile.pdf - like a relative path, the chrome preview dialog opens but it displays my 404 page.

The function ajax_get that retrieves the PDF has the following response headers:

Cache-Control:no-cache, no-store, must-revalidate
Connection:keep-alive
Content-Encoding:gzip
Content-Length:166
Content-Type:text/html; charset=UTF-8
Date:Tue, 26 Jan 2016 09:24:42 GMT
Expires:0
Pragma:no-cache
Server:nginx
Vary:User-Agent,Accept-Encoding
X-Powered-By:PHP/5.6.17

And retrieves the following json: {"status":1,"msg":"Added successfully", "pdf":"http:\/\/mywebsite.com\/public\/files\/somefile.pdf"}

After the json is received and after I send the path of pdf into the iFrame in the network tab of chrome console, the pdf retrieves as response headers:

Accept-Ranges:bytes
Cache-Control:no-cache, no-store, must-revalidate
Connection:keep-alive
Content-Length:52611
Content-Type:application/pdf
Date:Tue, 26 Jan 2016 09:24:42 GMT
Expires:0
Last-Modified:Tue, 26 Jan 2016 09:24:42 GMT
Pragma:no-cache
Server:nginx
Vary:User-Agent

Edit 2: I just tried with no success to retrieve the PDF from a PHP page, like so:

function display_pdf($url)
{
   header('Content-type: application/pdf');
   header('Content-Disposition: inline; filename="testing.pdf"');
   header('Content-Transfer-Encoding: binary');
   header('Accept-Ranges: bytes');
   echo file_get_contents(base_url() . $url);
}

And in javascript before sending to iFramePdf:

json.pdf = json.pdf.replace('http://mywebsite.com/', '');
json.pdf = base_url + 'backend/files/display_pdf/' + json.pdf;

The final url is something like: http://mywebsite/backend/files/display_pdf/public/files/somefile.pdf

If I enter that link in my browser it works..but in iframe it continues not to open the print preview from chrome.

Edit 3: I run a few more tests and the problem continues on iframe because it works in other ways. For example, the below code opens a new tab and automatically opens print preview dialog of chrome without any problem.

var win=window.open('about:blank');
win.document.write('<html><head></head><body>'); 
win.document.write('<iframe frameBorder="0" align="center" src="' + json.pdf + '" onload="test()" style="width: 100%; height: 100%"></iframe>'); 
win.document.write('<scr'+'ipt>function test(){window.focus();window.contentWindow.print()}</sc'+'ript></body></html>'); 
win.document.close(); 
if (window.focus) {win.focus()}

But I don't want to open a new tab. So I have tried to open a tab within the tab I'm in like so:

var printWindow = window.open(json.pathToPdf, "printWindow", "scrollbars=yes");
printWindow.focus();
printWindow.print();

And works, it opens a small tab within the tab I'm in, however it does not focus the chrome print preview dialog and if I'm working on fullscreen it shuts that off.

Edit 4: The problem is really because of PDF. If I change the code from:

$('body').append('<iframe class="hidden" id="iFramePdf" src="' + json.pdf + '"></iframe>');

to

$('body').append('<iframe class="hidden" id="iFramePdf" src="http://mywebsite.com/public/images/someimage.png"></iframe>');

or

$('body').append('<iframe class="hidden" id="iFramePdf" src="http://mywebsite.com/somepage.php"></iframe>');

It works without any problem.

If I set the PDF directly into the src the print preview dialog doesn't open but the PDF is loaded into the iframe..

$('body').append('<iframe class="hidden" id="iFramePdf" src="http://mywebsite.com/public/files/somepdf.pdf"></iframe>');
Linesofcode
  • 5,327
  • 13
  • 62
  • 116
  • The page where you run the code and the created iframe have the same origini? (same host and same protocol)? – Frogmouth Jan 25 '16 at 10:52
  • @Frogmouth yes yes. The PDF is retrieved from an AJAX call. Basically I ask the server to generate an PDF; the server appends the file into the disk; the server retrieves the file path; I send the PDF into the iframe. – Linesofcode Jan 25 '16 at 10:55
  • try this answer: http://stackoverflow.com/questions/16239513/print-pdf-directly-from-javascript – Frogmouth Jan 25 '16 at 11:04
  • The user uses a dynamic `setTimeout` for wait the loaded of the iframe. Maybe the iframe exposes `document.print` method after `1000` milliseconds and your code "fail". – Frogmouth Jan 25 '16 at 11:17
  • I have tried already to increase the timer to 5000 and the behaviour is the same. – Linesofcode Jan 25 '16 at 11:20
  • @frogmouth I just notice that in the chrome console I receive two lines of PDF, one is status 200 and the other is `canceled`. This only works if I send the PDF to the iframe..if I comment the line it does not receive any PDF. - Btw, this happens in local and server. – Linesofcode Jan 25 '16 at 11:39
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/101597/discussion-between-frogmouth-and-linesofcode). – Frogmouth Jan 25 '16 at 14:31
  • Sorry, it was my lunch time. – Linesofcode Jan 25 '16 at 15:55
  • @Frogmouth could you see my edited answer please? – Linesofcode Jan 26 '16 at 09:34
  • ... what i not understand is if in the iframe the browser open the PDF? – Frogmouth Jan 26 '16 at 12:23
  • maybe the name of file must be __dynamic__ in row `header('Content-Disposition: inline; filename="testing.pdf"');` not `testing.pdf` each time... – Frogmouth Jan 26 '16 at 12:28
  • @Frogmouth the iframe is hidden, but it opens the pdf..even with my original code. If I go to the DOM and remove the `hidden` class I can see that the PDF is OK. I have tried with dynamic name, but didn't work as well. :\ – Linesofcode Jan 26 '16 at 14:00

2 Answers2

1

After all my attempts, this really seems like an bug that no one knows about. It works on localhost but not on server. And the only problem is with PDF files, because with images and pages works fine.

I'll probably end up creating an image from the PDF file generated, which isn't a good solution since I can have multiple PDF pages.

Anyway, if anyone knows any solution or wants me to try anything I'll be happy to do it.

Linesofcode
  • 5,327
  • 13
  • 62
  • 116
1

Working code to print pdf when user clicks on print icon in the table.

1) Icon code to call js function :

<a href="javascript:printReport('<?= $userReport->pdf_file_name ?>')"><i class="btn-icon-only icon-large icon-print" title="Print Report"> </i></a>

2) A div element which is being used as a placeholder to display as well as print pdf :

<div id="view-report-holder"></div>

3) JS function to print the pdf report :

function printReport(pdfFileName)
{
  $('#view-report-holder').hide();
  $('#view-report-holder').html('');
  $('<iframe>', {
    src: '<?= $uploadDir['baseurl']."/pdf_reports/" ?>' + pdfFileName,
    frameborder: 0,
    id: 'view-report',
    scrolling: 'no'
  }).appendTo('#view-report-holder');
  var printTag = document.getElementById('view-report');
  printTag.contentWindow.print();
  return false;
}

Link and Function to display pdf under table : (Not necessary for print feature, btw)

<a href="javascript:viewReport('<?= $userReport->pdf_file_name ?>')"><i class="btn-icon-only icon-large icon-eye-open" title="View Report"> </i></a>
...
function viewReport(pdfFileName)
{
  $('#view-report-holder').show();
  $('#view-report-holder').html('');
  $('<iframe>', {
    src: '<?= $uploadDir['baseurl']."/pdf_reports/" ?>' + pdfFileName,
    frameborder: 0,
    scrolling: 'no'
  }).appendTo('#view-report-holder');
  $('html, body').animate({
    scrollTop: $("#view-report-holder").offset().top
  });
  return false;
}
Gaurav
  • 1,942
  • 19
  • 31