从phantomjs子进程发送节点中的二进制响应

时间:2015-08-11 10:44:58

标签: javascript node.js phantomjs

我创建了一个节点端点来为我的svg图表创建光栅化版本。

app.post('/dxexport', function(req, res){
    node2Phantom.createPhantomProcess(req,res);
});

我的幻像功能节点使用spawn来运行phantomjs

var spawn = require('child_process').spawn;
exports.createPhantomProcess = function(req,res){

    var userRequest = JSON.stringify(req.body);
    var bin = "node_modules/.bin/phantomjs"
    var args = ['./dxexport/exporter-server.js', userRequest, res];
    var cspr = spawn(bin, args);


    cspr.stdout.on('data', function (data) {
        var buff = new Buffer(data);
        res.send(data);
    });

    cspr.stderr.on('data', function (data) {
        data += '';
        console.log(data.replace("\n", "\nstderr: "));
    });

    cspr.on('exit', function (code) {
        console.log('child process exited with code ' + code);
        process.exit(code);
    });

};

当渲染完成并且文件成功创建时,我调用phantomjs中的renderCompleted函数:

var renderCompleted = function (parameters) {
    var exportFile = fileSystem.open(parameters.exportFileName, "rb"),
        exportFileContent = exportFile.read();
    parameters.response.statusCode = 200;
    parameters.response.headers = {
        "Access-Control-Allow-Origin": parameters.url,
        "Content-Type": contentTypes[parameters.format],
        "Content-Disposition": "attachment; fileName=" + parameters.fileName + "." + parameters.format,
        "Content-Length": exportFileContent.length
    };
    parameters.response.setEncoding("binary");
    parameters.response.write(exportFileContent);

    /////// somehow send exportFileContent as node res object for download \\\\\\\\
    exportFile.close();
    parameters.format !== "svg" && fileSystem.remove(parameters.exportFileName);
    for (var i = 0; i < parameters.filesPath.length; i++)
        fileSystem.remove(parameters.filesPath[i]);
    parameters.filesPath = [];
    parameters.response.close()
};

此响应是从nodejs传递的,但显然这段代码正在调用phantomjs方法,所以我得到错误,如

  

TypeError:'undefined'不是函数(评估'parameters.response.setEncoding(“binary”)')

如何以某种方式将二进制文件响应发送到节点功能,以便可以将我的节点服务器发送给用户?

感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

好的,经过一番努力,如果有人在这篇文章上发现,那么这是一个有效的解决方案。

正如Artjom B.所提到的,我发现最简单的方法是将可视化的渲染和文件创建委托给phantomjs。然后通过控制台发送与这些操作相关的所有参数。

  

还根据@ArtjomB更新了答案。建议用一个唯一的开头和结尾字符串包装发送的控制台消息,这样可以减少其他可能的未来输出被误认为是预期的渲染文件对象的风险

var renderCompleted = function (parameters) {
    console.log("STRTORNDRD" + JSON.stringify(parameters) + "ENDORNDRD");
};

然后它被stdout拾取并可以像这样使用:

exports.exportVisual = function (req, res) {

    var userRequest = JSON.stringify(req.body);
    var bin = "node_modules/.bin/phantomjs"
    var args = ['./dxexport/exporter-server.js', userRequest, res];
    var cspr = spawn(bin, args);
    var contentTypes = {
        pdf: "application/pdf",
        svg: "image/svg+xml",
        png: "image/png"
    };


    cspr.stdout.on('data', function (data) {

        var buff = new Buffer(data).toString('utf8');
        var strData = buff.match(new RegExp("STRTORNDRD" + "(.*)" + "ENDORNDRD"));

        if (strData) {

            var parameters = JSON.parse(strData[1]);

            var img = fs.readFileSync(parameters.exportFileName);
            var headers = {
                "Access-Control-Allow-Origin": parameters.url,
                "Content-Type": contentTypes[parameters.format],
                "Content-Disposition": "attachment; fileName=" + parameters.fileName + "." + parameters.format,
                "Content-Length": img.length
            };

            res.writeHead(200, headers);
            res.end(img, 'binary');

            // delete files after done
            if (parameters.format != "svg") {
                fs.unlink(parameters.exportFileName);
            }

            for (var i = 0; i < parameters.filesPath.length; i++)
                fs.unlink(parameters.filesPath[i]);

            // done. kill it
            cspr.kill('SIGINT');

        }

    });

    cspr.stderr.on('data', function (data) {
        data += '';
        console.log(data.replace("\n", "\nstderr: "));
    });

    cspr.on('exit', function (code) {
        console.log('child process exited with code ' + code);
        process.exit(code);
    });

};