PhantomJs: inline HTML with external CSS file

13,269

Solution 1

As benweet mentioned, you need to set page.content just once, as it will trigger a reload each time.

Because of that, in addition you will need to define your callbacks before actually setting the page content.

Try it like this instead:

var page = require('webpage').create();

page.onResourceRequested = function(requestData, request) {
  console.log('::loading', requestData['url']);  // this does get logged now
};

page.onLoadFinished = function() {
  console.log('::rendering');
  page.render('output.png');
  phantom.exit();
};

var content = '';
content += '<html><head>';
content += '<link rel="stylesheet" href="http://example.com/css/layout.css" type="text/css" media="screen">';
content += '</head><body>';
content += '<h1>test</h1>';
content += '</body></html>';
page.content = content;

Solution 2

You have a setting named localToRemoteUrlAccessEnabled controlling if local pages can access remote ressources. It appears to default to false so you should try to change that.

PhantomJS settings are documented here, so changing this setting would be done like that in your code:

page.settings.localToRemoteUrlAccessEnabled = true;

just after the page creation. Since your page content is generated through scripting, I don't know if it is really considered local or remote. If this setting doesn't work, you could try setting webSecurityEnabled to false.

Share:
13,269
EoghanM
Author by

EoghanM

Updated on June 26, 2022

Comments

  • EoghanM
    EoghanM almost 2 years

    I'm attempting to render some inline HTML which links to an external css file using the following PhantomJs script:

    var page = require('webpage').create();
    page.content = '';
    page.content += '<html><head>';
    page.content += '<link rel="stylesheet" href="http://example.com/css/layout.css" type="text/css" media="Screen">';
    page.content += '</head><body>';
    page.content += '<h1>test</h1>';
    page.content += '</body></html>';
    
    page.onResourceRequested = function(requestData, request) {
        console.log('::loading', requestData['url']);  // this doesn't get logged
    };
    
    page.onLoadFinished = function() {
        console.log('::rendering');
        page.render('output.png');
        phantom.exit();
    };
    

    The layout.css file can be accessed okay with wget

    But here's the output of phantomjs:

    $ ./phantomjs --debug=true render_demo.js
    ... snip ...
    2014-01-06T12:17:53 [DEBUG] WebPage - updateLoadingProgress: 10
    2014-01-06T12:17:53 [DEBUG] WebPage - updateLoadingProgress: 10
    2014-01-06T12:17:53 [DEBUG] WebPage - updateLoadingProgress: 100
    2014-01-06T12:17:53 [DEBUG] Network - Resource request error: 5 ( "Operation canceled" ) URL: "http://example.com/css/layout.css"
    ::rendering
    

    There is no output .png file created.

    Any ideas on how to ensure external CSS resources get fully loaded before rendering? It seems to work okay when I request the same html with page.open