2016-10-31 72 views
0

我在项目中使用节点画布;本质上该项目是关于在浏览器屏幕上显示图像,并能够通过REST API POSTs控制图像的位置。这工作正常,但在POST上我想自动刷新浏览器。Javascript节点js浏览器刷新POST

我已经看过:

  • NPM包(浏览器刷新等);但他们需要把一些代码放在客户端页面,但我没有任何HTML客户端页面。

  • 调用res.redirect;这似乎没有做任何事情。

  • 在POST方法中调用我的draw()方法:我得到'write after end'的错误。

有帮助吗?同样,问题是刷新浏览器(或其中的一部分)在POST方法中的新坐标上。

下面的代码。

干杯, 马特

节点server.js:

//Lets require/import the HTTP module 
var http = require('http'); 
var express = require('express'); 
var app = express(); 
var bodyParser = require('body-parser') 
var fs = require('fs') 
var path = require('path') 

var draw = require('./draw_badge'); 

var robot1; 
var robot1_xcoord = 30;  
var robot1_ycoord = 100;  

var robot2; 
var robot2_xcoord = 50; 
var robot2_ycoord = 30;  

/** bodyParser.urlencoded(options) 
* Parses the text as URL encoded data (which is how browsers tend to send form data from regular forms set to POST) 
* and exposes the resulting object (containing the keys and values) on req.body 
*/ 
app.use(bodyParser.urlencoded({ 
    extended: true 
})); 
/**bodyParser.json(options) 
* Parses the text as JSON and exposes the resulting object on req.body. 
*/ 
app.use(bodyParser.json()); 

/** -------- Start ----- 
* 
*/ 



    { 
    app.get('/', function (req, res) { 

    console.log("Xcoord: " + robot1_xcoord); 
    res.setHeader('Content-Type', 'image/png'); 
    // redraw everything 
    draw(robot1_xcoord,robot1_ycoord, robot2_xcoord,robot2_ycoord).pngStream().pipe(res); 

}); 


// Getting a POST 
app.post('/', function (req, res) { 
    console.log(req.body.id); 
if (req.body.id=="1") 
{ 
    console.log("robot1 change"); 
    robot1_xcoord = req.body.xcoordinate; 
    robot1_ycoord = req.body.ycoordinate; 
} 
else 
if (req.body.id=="2") 
{ 
    console.log("robot2 change"); 

    robot2_xcoord = req.body.xcoordinate; 
    robot2_ycoord = req.body.ycoordinate; 
} 
// draw(robot1_xcoord,robot1_ycoord, robot2_xcoord,robot2_ycoord).pngStream().pipe(res); 
//res.redirect('localhost:5000'); 
res.send('Got a POST request'); 

// try 
//res.redirect(req.get('referer')); 
/* 
return http.get({ 
     host: 'localhost', 
     path: '/' 
    }, function(response) { 
     // Continuously update stream with data 
     var body = ''; 
     response.on('data', function(d) { 
      body += d; 
     }); 
     response.on('end', function() { 

      // Data reception is done, do whatever with it! 
      var parsed = JSON.parse(body); 

     }); 
    }); 
*/ 

}); 
// Main app - Listen 
app.listen(process.env.PORT || 5000, function() { 
    console.log('Example app listening !'); 
}); 

draw_badge.js:

var Canvas = require('canvas') 
var fs = require('fs') 


function draw_badge(x,y) { 


    var x, y, i 

    ctx.clearRect(0, 0, 120, 120) 

    ctx.save() 

    ctx.translate(160, 160) 
    ctx.beginPath() 
    ctx.lineWidth = 14 
    ctx.strokeStyle = '#325FA2' 
    ctx.fillStyle = '#eeeeee' 

    ctx.arc(x, y, 42, 0, Math.PI * 2, true) 
    ctx.stroke() 
    ctx.fill() 


return canvas; 
} 


function draw_robot(x,y) { 

var Image = Canvas.Image 
var canvas = new Canvas(600, 600) 
var ctx = canvas.getContext('2d') 


var img = new Image() 
img.src = canvas.toBuffer() 
ctx.drawImage(img, 0, 0, 50, 50) 
ctx.drawImage(img, 50, 0, 50, 50) 
ctx.drawImage(img, 100, 0, 50, 50) 

img.src = fs.readFileSync('./kuka.png') 
ctx.drawImage(img, 100, 0, img.width , img.height) 

//img = new Image() 
img.src = fs.readFileSync('./robot.jpeg') 
ctx.drawImage(img, x, y, img.width/2, img.height/2) 
// new 


canvas.createPNGStream().pipe(fs.createWriteStream('./image-robot.png')) 
return canvas 

} 

function draw(x1,y1,x2,y2) 
{ 
    Image = Canvas.Image, 
     canvas = new Canvas(600, 600), 
     ctx = canvas.getContext('2d'); 
    canvas = draw_robot(x1,y1); 
    canvas = draw_badge(x2,y2); 
    return canvas; 
} 

module.exports = draw; 
+0

什么触发了POST?如果除了客户端的图片之外没有其他东西,你不能拥有POST吗?客户是什么?如果客户端是网络浏览器,则不能在没有HTML和/或JS的情况下进行POST ... – jcaron

+0

对服务器的调用(即curl调用)会触发POST,并具有关于在哪里绘制图像的坐标信息。 node-canvas允许我从服务器端渲染图片..(请参阅draw_badge.js ..) – MattLieber

回答

1

他们的方式你想不能工作

  • 已交付给浏览器无法动态刷新,仅仅是因为它是一个图像的图像。一旦服务器已经交付并且客户端加载他们的工作完成。
  • 尝试写入请求(可能是数百个请求中的一个)当然会导致“写入结束后”,因为请求的结尾是图像首次加载到浏览器中的时间。
  • 快速res.redirect函数不能在事后调用(请求后),也可以立即重定向,这是你不需要的。

简单的解决方案:通过HTTP标头(正确)

app.get('/', function (req, res) { 
    console.log("Xcoord: " + robot1_xcoord); 
    res.setHeader('Content-Type', 'image/png'); 
    // refresh every second 
    res.setHeader('Refresh','1'); 
    // redraw everything 
    draw(robot1_xcoord,robot1_ycoord,robot2_xcoord,robot2_ycoord).pngStream().pipe(res); 

}); 

真正的解决方案刷新:流媒体图像

你可以提供一个实际的图像流。这个想法是,您对图片的请求永远不会被关闭,并且当您通过REST-API更改图片时,下一张图片将被传送。从理论上讲,你的浏览器会显示它所得到的最后一个完整的框架,从而在浏览器窗口中“更新”你的图像。这将是这里的real解决方案,但是在实施时浪费的时间可能会很昂贵。这会在代码中进行一些重新安排。

警告:仅Firefox,Chrome的支持已被删除,因为我刚刚得知:/

server.js

//Lets require/import the HTTP module 
var http = require('http'); 
var express = require('express'); 
var app = express(); 
var bodyParser = require('body-parser') 
var fs = require('fs') 
var path = require('path') 

var draw = require('./draw_badge'); 

var robot1; 
var robot1_xcoord = 30; 
var robot1_ycoord = 100; 

var robot2; 
var robot2_xcoord = 50; 
var robot2_ycoord = 30; 

// An array to hold a list of active clients 
var clients = []; 

// draw an initial version of your buffer 
var imageData = draw(robot1_xcoord, robot1_ycoord, robot2_xcoord, robot2_ycoord).toBuffer(undefined, 3, canvas.PNG_FILTER_NONE); 
// get the size in bytes as well, we'll need it 
var length = imageData.byteLength; 

/** bodyParser.urlencoded(options) 
* Parses the text as URL encoded data (which is how browsers tend to send form data from regular forms set to POST) 
* and exposes the resulting object (containing the keys and values) on req.body 
*/ 
app.use(bodyParser.urlencoded({ 
    extended: true 
})); 
/**bodyParser.json(options) 
* Parses the text as JSON and exposes the resulting object on req.body. 
*/ 
app.use(bodyParser.json()); 

/** -------- Start ----- 
* 
*/ 

app.get('/', function(req, res) { 
    // prepare header so that the browser will wait for arbitray updates 
    res.writeHead(200, { 
    'Content-Type': 'multipart/x-mixed-replace; boundary=--NEW_IMAGE_HERE', 
    'Cache-Control': 'no-cache', 
    'Connection': 'close', 
    'Pragma': 'no-cache' 
    }); 
    var on_update = function(imageData, length) { 
     try { 
     console.log("Updating client.. bytes:", length) 
     res.write("--NEW_IMAGE_HERE\r\n"); 
     res.write("Content-Type: image/png\r\n"); 
     res.write("Content-Length: " + length + "\r\n\r\n"); 
     res.write(imageData); 
     } catch (e) { // in case of an error remove from the clients array 
     console.log("Error: ", e); 
     clients.splice(clients.indexOf(on_update), 1); 
     } 
    } 
    // remove on disconnect 
    res.on('close', function() { 
    console.log("Disconnected"); 
    clients.splice(clients.indexOf(on_update), 1); 
    }); 
    // send the client our last cached version of the image 
    on_update(imageData, length); 
    // add our update function to the array of clients 
    clients.push(on_update); 
}); 

// Getting a POST 
app.post('/', function(req, res) { 
    console.log(req.body.id); 
    if (req.body.id == "1") { 
    console.log("robot1 change"); 
    robot1_xcoord = req.body.xcoordinate; 
    robot1_ycoord = req.body.ycoordinate; 
    } else 
    if (req.body.id == "2") { 
    console.log("robot2 change"); 
    robot2_xcoord = req.body.xcoordinate; 
    robot2_ycoord = req.body.ycoordinate; 
    } 
    res.send('Got a POST request'); 
    // redraw everything into the buffer 
    imageData = draw(robot1_xcoord, robot1_ycoord, robot2_xcoord, robot2_ycoord).toBuffer(undefined, 3, canvas.PNG_FILTER_NONE); 
    length = imageData.byteLength; 
    // notify active clients 
    for (on_update of clients) { 
    on_update(imageData, length); 
    } 
}); 
// Main app - Listen 
app.listen(process.env.PORT || 5000, function() { 
    console.log('Example app listening !'); 
});