1

I have a PhantomJS script that goes through folders in my file system and takes screenshots of HTML pages.

Because of window size and a variety of issues explained here I've opted to place the HTML file in an Object of the width and height of my choosing and then take a screenshot of that instead.

If I create a basic HTML file with an object with a relative data URL and open it in my browser, it works perfectly.

Here's an overview of my file structure.

.
├── dist
|   ├── page_one
|       └── page_one.html
|   └── page_two
|       └── page_two.html
└── tools
    └── screenshot.js

The code below, is saved in a file I call screenshot.js. I want to be able to run this through PhantomJS. It essentially reads through a comma separated string of directories (eg page_one,page_two), navigates to those pages, takes a screenshot and moves onto the next one. But despite the fact that the HTML generated is the same as the test file I created earlier, the screenshots are always blank.

If I replace the relative data URL with an absolute path, the script works perfectly, but obviously this isn't very re-usable if the file path has to be changed for every project.

I've tried using a number of ../ before the relative data url, but this still doesn't work.

var args = require('system').args,
    resourceWait  = 300,
    maxRenderWait = 10000,
    filesbefore   = "page_one,page_twoK",
    files         = filesbefore.split(','),
    mode          = 'iframe',
    page          = require('webpage').create(),
    count         = 0,
    forcedRenderTimeout,
    renderTimeout;

page.viewportSize = { width: 1024, height : 768 };

function doRender() {
    page.render(filename);
    next();
}

page.onResourceRequested = function (req) {
    count += 1;
    clearTimeout(renderTimeout);
};

page.onResourceReceived = function (res) {
    if (!res.stage || res.stage === 'end') {
        count -= 1;
        if (count === 0) {
            clearTimeout(forcedRenderTimeout);
            renderTimeout = setTimeout(doRender, resourceWait);
        }
    }
};

page.onConsoleMessage = function (msg) {
    console.log("from page: " + msg);
};

function evaluateJsWithArgs(func) {
    var args = [].slice.call(arguments, 1);
    var fn = "function() { return (" + func.toString() + ").apply(this, " + JSON.stringify(args) + "); }";
    return page.evaluate(fn);
};

function next(error) {
    if(!error) {
        if (files.length == 0){
            phantom.exit();
        }else{
            takeScreenshot(files.pop());
        }
    }
}

function takeScreenshot(file){
    var url = 'dist/' + file + '/' + file + '.html';
    filename = file + '.png';
    page.open('about:blank', function (status) {
        if (status !== "success") {
            console.log('Unable to load url');
            phantom.exit();
        } else {
            page.includeJs(
                "https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js",
                function() {
                    evaluateJsWithArgs(
                        function(url, w, h) {
                            console.log(url);
                            $('body')
                                .css({margin: 0, padding: 0})
                                .html('<object style="background: red;" data="../' + url + '" width="'+ w + '" height="' + h + '" id="screen-frame" />');

                                console.log($('body').html());
                        },
                        url,
                        page.viewportSize.width,
                        page.viewportSize.height
                    );
                }
            );

            forcedRenderTimeout = setTimeout(function () {
                doRender();
            }, maxRenderWait);
        }
    });
}

takeScreenshot(files.pop());

Please can someone tell me why this doesnt work.

Thanks in advance.

-

Note: If you'd like to run this locally, then create a basic file structure like mine above, download PhantomJS, cd to root directory of the project and run phantomjs tools/screenshot.js.

-

EDIT After searching I've found this Q&A. So to my understanding, PhantomJS just can't open local files when using a relative path.

Having an absolute path isn't a suitable option as it will never always be the same.

The only other option I can find at the moment is to put the files on a local server and then run the script from the server URL.

Community
  • 1
  • 1
Oliver Evans
  • 960
  • 1
  • 20
  • 43
  • So i've found a quick fix for this. Instead of opening a 'about:blank' page, i've create a html page with my html headers and empty body tags. And open that page instead. That fixes my issue but its not ideal, so ill leave this open incase anyone else has any ideas. – Oliver Evans Jan 20 '15 at 18:08

0 Answers0