【发布时间】:2015-11-18 21:12:05
【问题描述】:
我正在使用 Node.js 创建媒体上传微服务。该服务的工作原理是将上传的二进制数据接收到缓冲区,然后使用 S3 npm 包上传到 S3 存储桶。我正在尝试使用该包中存在的 eventEmitter 来显示上传到 S3 的数据量,并将其发送回正在上传的客户端(以便他们可以看到上传进度)。我正在使用 socket.io 将进度数据发送回客户端。
我遇到的问题是 socket.io 中的 .emit 事件会将上传进度数据发送到所有连接的客户端,而不仅仅是启动上传的客户端。据我了解,套接字连接到“连接”上的默认房间,该房间由客户端的“id”镜像。根据官方文档,使用 socket.to(id).emit() 应该只将范围内的数据发送到该客户端,但这对我不起作用。
更新示例代码:
server.js:
var http = require('http'),
users = require('./data'),
app = require('./app')(users);
var server = http.createServer(app);
server.listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
var io = require('./socket.js').listen(server);
socket.js:
var socketio = require('socket.io');
var socketConnection = exports = module.exports = {};
socketConnection.listen = function listen(app) {
io = socketio.listen(app);
exports.sockets = io.sockets;
io.sockets.on('connection', function (socket) {
socket.join(socket.id);
socket.on('disconnect', function(){
console.log("device "+socket.id+" disconnected");
});
socketConnection.upload = function upload (data) {
socket.to(socket.id).emit('progress', {progress:(data.progressAmount/data.progressTotal)*100});
};
});
return io;
};
s3upload.js:
var config = require('../config/aws.json');
var s3 = require('s3');
var path = require('path');
var fs = require('fs');
var Busboy = require('busboy');
var inspect = require('util').inspect;
var io = require('../socket.js');
...
var S3Upload = exports = module.exports = {};
....
S3Upload.upload = function upload(params) {
// start uploading to uploader
var uploader = client.uploadFile(params);
uploader.on('error', function(err) {
console.error("There was a problem uploading the file to bucket, either the params are incorrect or there is an issue with the connection: ", err.stack);
res.json({responseHTML: "<span>There was a problem uploading the file to bucket, either the params are incorrect or there is an issue with the connection. Please refresh and try again.</span>"});
throw new Error(err);
}),
uploader.on('progress', function() {
io.upload(uploader);
}),
uploader.on('end', function(){
S3Upload.deleteFile(params.localFile);
});
};
在使用 DEBUG=* node myapp.js 时,我看到 socket.io-parser 接收了这些信息,但它没有将它发送给客户端:
socket.io-parser encoding packet {"type":2,"data":["progress",{"progress":95.79422221709825}],"nsp":"/"} +0ms
socket.io-parser encoded {"type":2,"data":["progress",{"progress":95.79422221709825}],"nsp":"/"} as 2["progress",{"progress":95.79422221709825}] +0ms
但是,如果我删除此代码的 .to 部分,它会将数据发送给客户端(尽管发送给所有客户端,这根本无济于事):
io.sockets.on('connection', function(socket) {
socket.join(socket.id);
socket.emit('progress', {progress: (data.progressAmount/data.progressTotal)*100});
});
DEBUG=* 节点 myapp.js:
socket.io:client writing packet {"type":2,"data":["progress",{"progress":99.93823786632886}],"nsp":"/"} +1ms
socket.io-parser encoding packet {"type":2,"data":["progress",{"progress":99.93823786632886}],"nsp":"/"} +1ms
socket.io-parser encoded {"type":2,"data":["progress",{"progress":99.93823786632886}],"nsp":"/"} as 2["progress",{"progress":99.93823786632886}] +0ms
engine:socket sending packet "message" (2["progress",{"progress":99.93823786632886}]) +0ms
engine:socket flushing buffer to transport +0ms
engine:ws writing "42["progress",{"progress":99.84186540937002}]" +0ms
engine:ws writing "42["progress",{"progress":99.93823786632886}]" +0ms
我在这里做错了什么?是否有其他方法可以将事件从服务器仅发送到我缺少的特定客户端?
【问题讨论】:
标签: javascript node.js amazon-s3 socket.io