Google Docs Viewer occasionally failing to load content in iframe
Asked Answered
G

5

46

I'm having an issue with the Google Docs viewer that is causing a nightmare to solve because it only happens intermittently. I'm looking for guidance on how to make the content in the iframe load everytime without issue as it should.

Steps to reproduce 1) This page is a basic HTML page with a h1 tag and an iframe containing a link to a PDF on the same server

http://bit.ly/1mqbuf7

2) When you load the page, the pdf document will load in the iframe 60% of the time.

3) If you hit refresh 10 or so times, at least once it will fail to appear. Google returns a 307 first (Which it also does when it works) and then returns a 204 - no content. When it works, it returns a 200, with the content you see in the viewer.

I'm struggling to understand why it only does this some of the time with no visible errors. This has been tested and failed on Google Chrome v 48.0.2564.103 (PC) and Internet Explorer Edge v25.10586 (PC) with the same results and frequency of failure.

Any guidance would be greatly appreciated.

Gonfalon answered 9/2, 2016 at 17:49 Comment(2)
Running into similar problems just today. Posted a new question: #40414539Radarscope
Same issue for me. Incredible bug. Tried everything without success.Brahma
E
4

This is not fixing your problem per se, but since I had the same problem and I eventually managed to find an acceptable solution, I thought I'd share it.

var $docViewer = $(`<iframe src="${newValue}" height="100%" width="100%"></iframe>`);
//If using modern browser, use and embed object
if (window.chrome || typeof (window.mozInnerScreenX) != "undefined")
  $docViewer = $(`<object width="100%" height="100%" data="${newValue}" type="application/pdf">
                    <embed src="${newValue}" type="application/pdf">
                        <p>This browser does not support PDFs.Please download the PDF to view it: <a href="${newValue}">Download PDF</a>.</p>
                    </embed>
                </object>`);
//Add the new viewer
$docViewer.appendTo($("#invoicePreview"));

Basically, use an embed if modern browser, and the gviewer if not. The embed object behaves identically to the google doc viewer, it works in 100% of cases (no failed loads), but since it's not supported for IE and/or low-end mobile devices, use the google doc viewer for that... Progressive Enhancements I guess.

Eidolon answered 7/9, 2017 at 11:49 Comment(0)
U
2

Here's a "hack" that will ensure a proper loading every time (albeit with some delay, due to potential failed attempts - it's Google's fault, don't shoot the messenger!). The 2s interval duration can be modified to best fit the time expected for a successful effort to start loading the iFrame.

HTML:

<div id="test-id-1" style="text-align: center; width: 100%; height: 1150px" class="embed-pdf" data-url="{insert_pdf_link_here}"><span class="loader">Please wait...</span></div>

JS:

$(document).ready(function() {

    let embed_pdfs = {};

    $('.embed-pdf').each(function() {
        var $pdfViewer = $('<iframe src="https://docs.google.com/viewer?url=' + $(this).data('url') + '&embedded=true" style="width: 100%; height: 100%" frameborder="0" scrolling="no"></iframe>');
        $pdfViewer.appendTo($(this));
        console.log($(this).attr('id') + " created");
        embed_pdfs[$(this).attr('id')] = 'created';
    });

    $(document).find('.embed-pdf iframe').load(function(){
        embed_pdfs[$(this).parents('.embed-pdf').attr('id')] = 'loaded';
        $(this).siblings('.loader').remove();
        console.log($(this).parents('.embed-pdf').attr('id') + " loaded");
    });

    let embed_pdf_check = setInterval(function() {
        let remaining_embeds = 0;
        $.each(embed_pdfs, function(key, value) {
            try {
                if ($($('#' + key)).find('iframe').contents().find("body").contents().length == 0) {
                    remaining_embeds++;
                    console.log(key + " resetting");
                    $($('#' + key)).find('iframe').attr('src', src='https://docs.google.com/viewer?url=' + $('#' + key).data('url') + '&embedded=true');
                }
            }
            catch(err) {
                console.log(key + " reloading");
            }
        });
    
        if (!remaining_embeds) {
            clearInterval(embed_pdf_check);
        }
    }, 2000);
});
Underpants answered 18/10, 2020 at 15:18 Comment(0)
E
2
<!DOCTYPE html>
<html lang="en">
<head>
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
    <div id="iframeContainer"></div>
</body>
<script>
    
    var URL = "https://docs.google.com/viewer?url=http://www.africau.edu/images/default/sample.pdf&embedded=true";
    var count = 0;
        var iframe = ` <iframe id = "myIframe" src = "${URL}" style = "width:100%; height:500px;"  frameborder = "0"></iframe>`;
            
       $(`#iframeContainer`).html(iframe);
            $('#myIframe').on('load', function(){ 
            count++;
            if(count>0){
                clearInterval(ref)
            }
        });

        var ref = setInterval(()=>{
        $(`#iframeContainer`).html(iframe);
        $('#myIframe').on('load', function() {
            count++;
            if (count > 0) {
                clearInterval(ref)
            }
        });
    }, 4000)
</script>
</html>
Change var URL = your_googel_docs_pdf_url
The code will keep loading the url into iframe until the doc loads successfully.
Endsley answered 7/8, 2021 at 4:15 Comment(2)
Hi and welcome to stackoverflow, here are some guidelines : it is not recommended to post code-only answers, answers should provide more explanation about the code to make it the answer more useful and are more likely to attract upvotesIodic
Unfortunately, this code went in infinite loop cause count increment is not considered by browser and document get auto load & hide after 4 seconds.Iraq
P
1

It's not the best solution. But I waited a few seconds after the page loaded and checked if the iframe was loaded (see how below). If it wasn't, then I set the iframe's src attribute to null and then back to the correct source, affectively reloading it. Then waited a few seconds to check again and repeated. Once it has loaded you can stop checking.

        conditionalPdfIFrameReloadTimeout() {
            setTimeout(() => {
                let iFrame = document.GetElementById("pdfIframe")
                if (iFrame.contentDocument/*pdf iframe failed to load*/) {    
                    iFrame.src = null
                    iFrame.src = "the url to your pdf"
                    conditionalPdfIFrameReloadTimeout()
                }
            }, 6000)
        }
Periodontics answered 16/9, 2022 at 8:5 Comment(0)
R
-1

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en" style="width:100%; height:100%;">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

  <meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body id="iframeContainer" style="height: 100%; width: 100%; overflow: hidden; margin:0px;">
<script>
    
    var URL = "https://docs.google.com/gview?url=enteryoururl&embedded=true";
    var count = 0;
        var iframe = `<iframe id = "myIframe" src = "${URL}" style="width:100%; height:100%;" frameborder="0" allowfullscreen=""></iframe>`;
            
       $(`#iframeContainer`).html(iframe);
            $('#myIframe').on('load', function(){ 
            count++;
            if(count>0){
                clearInterval(ref)
            }
        });

        var ref = setInterval(()=>{
        $(`#iframeContainer`).html(iframe);
        $('#myIframe').on('load', function() {
            count++;
            if (count > 0) {
                clearInterval(ref)
            }
        });
    }, 2000)
</script>
</body>
</html>

The above code worked for me.

Rufous answered 21/12, 2021 at 9:19 Comment(1)
Can you edit your answer to say what you changed and why this should fix the issue ?Arachne

© 2022 - 2024 — McMap. All rights reserved.