带有节点(socket.io和formidable)和ajax的文件上载进度条

时间:2014-04-18 19:13:39

标签: ajax node.js socket.io formidable

我正在教自己一些Ajax,本课程需要在本地构建一个简单的文件上传表单。我在Windows 7上运行XAMPP,虚拟主机设置为http://test。本书中的解决方案是使用节点和一个名为“multipart”的几乎未知的包,该包应该解析表单数据,但却在我身上挣扎。

我找到了最好的工作包,这似乎是艰巨的。它完成了这个技巧,我的文件将在本地上传,我通过Ajax获取所有细节。但是,它不会与本书中的简单JS代码一起发挥作用,该代码用于在progress元素中显示上载进度。所以,我环顾四周,人们建议使用socket.io将进度信息发回客户页面。

我已经成功地在本地工作,并且我设法让socket.io使用一些基本的教程。现在,我不能为我的生活让他们一起工作。我甚至无法将一个简单的控制台日志消息从socket.io发送回我的页面,而强大的做法就是这样。

首先,这是文件上传表单本身。 upload.html页面中的脚本:

document.getElementById("submit").onclick = handleButtonPress;
var httpRequest;

function handleResponse() {
    if (httpRequest.readyState == 4 && httpRequest.status == 200) {
        document.getElementById("results").innerHTML = httpRequest.responseText;
    }
}

function handleButtonPress(e) {
    e.preventDefault();

    var form = document.getElementById("myform");
    var formData = new FormData(form);

    httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = handleResponse;
    httpRequest.open("POST", form.action);
    httpRequest.send(formData);
}

这是相应的节点脚本(重要的部分是form.on('progress')

var http = require('http'),
    util = require('util'),
    formidable = require('formidable');

http.createServer(function(req, res) {
  if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
    var form = new formidable.IncomingForm(),
        files = [],
        fields = [];

    form.uploadDir = './files/';
    form.keepExtensions = true;

    form
      .on('progress', function(bytesReceived, bytesExpected) {
        console.log('Progress so far: '+(bytesReceived / bytesExpected * 100).toFixed(0)+"%");
      })
      .on('file', function(name, file) {
        files.push([name, file]);
      })
      .on('error', function(err) {
        console.log('ERROR!');
        res.end();
      })
      .on('end', function() {
        console.log('-> upload done');
        res.writeHead(200, "OK", {
            "Content-Type": "text/html", "Access-Control-Allow-Origin": "http://test"
        });
        res.end('received files: '+util.inspect(files));
      });
    form.parse(req);
  } else {
    res.writeHead(404, {'content-type': 'text/plain'});
    res.end('404');
  }
  return;
}).listen(8080);

console.log('listening');

好的,这样一切都按预期工作。现在这里是最简单的socket.io脚本,我希望将其注入前两个脚本,将进度信息发送回我的页面。这是客户端代码:

var socket = io.connect('http://test:8080');

socket.on('news', function(data){
    console.log('server sent news:', data);
});

这是服务器端节点脚本:

var http = require('http'),
    fs = require('fs');

var server = http.createServer(function(req, res) {
    fs.createReadStream('./socket.html').pipe(res);
});

var io = require('socket.io').listen(server);

io.sockets.on('connection', function(socket) {
    socket.emit('news', {hello: "world"});
});

server.listen(8080);

所以这本身工作正常,但是当我尝试将socket.io代码放在我的表单中时,我的问题出现了......我已经尝试将它放在任何可能远程有意义的地方,我尝试了异步fs.readFile的模式,但它不会向客户端发送任何内容 - 同时文件上传部分仍然可以正常工作。我需要在两个包之间建立某种握手吗?帮帮我吧我是一个前端人员,所以我对这个后端的东西不太熟悉。我暂时把它放在一边,然后转到其他课程上。

1 个答案:

答案 0 :(得分:0)

也许您可以为一个客户创建一个房间,然后将百分比广播到这个房间。

我在这里解释了:How to connect formidable file upload to socket.io in Node.js