Съдържанието на долния колонтитул изглежда не работи

Опитвам се да създам персонализирани долни колонтитули като примери за phantomjs: https://github.com/ariya/phantomjs/blob/master/examples/printheaderfooter.js

Ето моят код:

var phantom = require('node-phantom');

phantom.create(function (err, ph) {
    ph.createPage(function (err, page) {
         page.set('paperSize', {
              format: 'A4',
              orientation: 'portrait',
              footer: {
                contents: ph.callback(function (pageNum, numPages) {
                  if (pageNum == 1) {
                    return "";
                  }
                  return "<h1>Header <span style='float:right'>" + pageNum + " / " + numPages + "</span></h1>";
                })
              }
         }, function () {
             page.open('http://www.google.com', function () {
              })
         })
    })
});

Но за съжаление получавам следната грешка:

TypeError: Object #<Object> has no method 'callback';

Грешка ли е, че ph не излага метода за обратно извикване?


person Erik    schedule 14.06.2013    source източник


Отговори (4)


Има два проблема във вашия скрипт:

  • ph не е класическият фантомен обект, а прокси обект. node-phantom използвайте уеб сокети за извикване на phantomjs. Разбира се, някои функции се губят при тази реализация.
  • функциите не се сериализират при извикване на page.set

Отпечатването на персонализиран горен/долен колонтитул също изисква извикване на phantom.callback. Този метод не е документиран и затова не е изложен от node-phantom (и не може да бъде). Трябва да намерим начин да приложим този метод в този пакет.

Има много решения. Ето моето възможно решение:

Сериализирайте вашите функции в низ във вашия скрипт

var phantom = require('node-phantom');

phantom.create(function (err, ph) {
    ph.createPage(function (err, page) {
         page.set('paperSize', {
              format: 'A4',
              orientation: 'portrait',
              header: {
                            height: "1cm",
                            contents: 'function(pageNum, numPages) { return pageNum + "/" + numPages; }'
                        },
                        footer: {
                            height: "1cm",
                            contents: 'function(pageNum, numPages) { return pageNum + "/" + numPages; }'
                        }
         }, function () {   
             page.open('http://www.google.fr', function () {        
             page.render('google.pdf');
             ph.exit();
              })
         })
    })
});

редактирайте bridge.js и добавете phantom.callback + eval. Това ни позволява да включим отново горния/долния колонтитул .contents.

case 'pageSet':
            eval('request[4].header.contents = phantom.callback('+request[4].header.contents+')');
            eval('request[4].footer.contents = phantom.callback('+request[4].footer.contents+')');
            page[request[3]]=request[4];
            respond([id,cmdId,'pageSetDone']);
            break;

Както можете да видите, това работи! (Google на френски)

въведете описание на изображението тук

person Cybermaxs    schedule 17.06.2013
comment
Благодаря. Това работи добре. Разбира се, ще ти дам наградата. Мога ли да ви попитам за един въпрос. Какво мислите за този мост (имам предвид node-phantom) за phantomjs? Дали е хак или добро решение за работа с phantomjs в nodejs? - person Erik; 18.06.2013
comment
добре, добрият въпрос е: трябва ли да използваме phantomjs с node.js? Има добър отговор на stackoverflow.com/ questions/15745394/ особено Phantom и node имат непреодолими различия. Лично аз не съм голям фен, но понякога трябва да правим лоши неща, само за да свършим работата. - person Cybermaxs; 18.06.2013
comment
@Cybermaxs, работи чудесно, как можем да получим общия брой страници?stackoverflow.com/questions/23516294/ - person Muhammad Rashid; 09.05.2014
comment
Ако не сте доволни от node-phantom, можете също да опитате phridge (github.com/peerigon/phridge). Той осигурява по-чист и по-интуитивен начин за стартиране на скриптове в PhantomJS и връщане на резултатите обратно към възела. - person Johannes Ewald; 26.05.2014
comment
да Това е само моето скромно мнение. Ако не ви харесва, давайте :) - person Johannes Ewald; 26.05.2014

За съжаление node-phantom изглежда не поддържа phantom.callback. Тъй като проектът е неактивен повече от година, мисля, че е малко вероятно да бъде актуализиран в близко бъдеще.

От друга страна, phantomjs-node поддържа phantom.callback() от версия 0.6.6. Можете да го използвате по следния начин:

var phantom = require('phantom');

phantom.create(function (ph) {
    ph.createPage(function (page) {
        page.open("http://www.google.com", function (status) {

            var paperConfig = {
                format: 'A4',
                orientation: 'portrait',
                border: '1cm',
                header: {
                    height: '1cm',
                    contents: ph.callback(function(pageNum, numPages) {
                        return '<h1>My Custom Header</h1>';
                    })
                },
                footer: {
                    height: '1cm',
                    contents: ph.callback(function(pageNum, numPages) {
                        return '<p>Page ' + pageNum + ' / ' + numPages + '</p>';
                    })
                }
            };

            page.set('paperSize', paperConfig, function() {
                // render to pdf
                page.render('path/to/file.pdf', function() {
                    page.close();
                    ph.exit();
                });
            });
        });
    });
});

Както можете също да видите в това същност.

person Ricardo Torres    schedule 19.11.2014
comment
Вече не използвам модул node-phantom и намирам по-добър github.com/peerigon/phridge - person Erik; 20.11.2014
comment
Ерик, благодаря много. Phridge е значително по-опростен от останалите - person kibibu; 09.03.2016

node phantom изглежда излага този прокси-обект чрез функцията create (това трябва да е вашият ph-обект):

var proxy={
                createPage:function(callback){
                    request(socket,[0,'createPage'],callbackOrDummy(callback));
                },
                injectJs:function(filename,callback){
                    request(socket,[0,'injectJs',filename],callbackOrDummy(callback));
                },
                addCookie: function(cookie, callback){
                    request(socket,[0,'addCookie', cookie],callbackOrDummy(callback));
                },
                exit:function(callback){
                    request(socket,[0,'exit'],callbackOrDummy(callback));
                },
                on: function(){
                    phantom.on.apply(phantom, arguments);
                },
                _phantom: phantom
            };

това означава, че вероятно можете да получите достъп до обратното извикване на фантомите по следния начин:

ph._phantom.callback
person hereandnow78    schedule 14.06.2013
comment
За съжаление получавам следната грешка: Хванато изключение: TypeError: Object #‹ChildProcess› has no method 'callback'; - person Erik; 14.06.2013
comment
тогава съжалявам, тогава не виждам как мога да ти помогна там - person hereandnow78; 14.06.2013

Ето какво направих за достъп до phantom.callback:

добавете това към node-phantom.js ред 202:

callback: function(callback){
  request(socket,[0,'callback'],callbackOrDummy(callback));
},

точно преди _phantom: phantom

и добавете това към bridge.js ред 45:

case 'callback':
    phantom.callback(request[3]);
break;

Дано помогне!

person rafaelcastrocouto    schedule 17.06.2013
comment
Работи ли това решение за вас? Добавих кода по-горе и сега не получавам грешката, но не получавам и долен колонтитул. Сигурен ли си, че е достатъчно? - person Erik; 17.06.2013
comment
Току-що ви показах как да получите достъп до обекта phantom.callback, не цялото решение ... добре, добрият въпрос е: трябва ли да използваме phantomjs с node.js? страхотен въпрос #Cybermaxs - Betclic - person rafaelcastrocouto; 19.06.2013