【问题标题】:Upload Files with Websockets and Nodejs使用 Websockets 和 Nodejs 上传文件
【发布时间】:2014-01-04 02:45:29
【问题描述】:

我正在尝试实现一个文件上传器,其中 HTML 输入文件由 WebSocket 发送到 Nodejs 服务器。

尝试从 HTML 的 FileReader API 读取 BLOB 和二进制字符串中的文件,并将其发送到 Nodejs 服务器,以便将其写入服务器中的文件。在 Nodejs 部分尝试使用 ascii 或 base 64 编码的 createWriteStream 和 writeFile。

服务器中保存的文件仍然无法正常工作。

我错过了什么吗?

谢谢

更新

客户

    var uploader = $("#uploader"),
        files = uploader.prop('files'),
        file_reader = new FileReader();
    file_reader.onload = function(evt) {
        socketClient.write({
            'action': 'ExtensionSettings->upload', 
            'domain': structureUser.domain, 
            'v_id': ext, 
            'file': file_reader.result
        });
    };
    file_reader.readAsDataURL(files[0]);
    //readAsDataURL
    uploader.replaceWith(uploader.clone());

服务器

var stream = fs.createWriteStream("file");
stream.once("open", function() {
    stream.write(msg.file, "base64");
    stream.on('finish', function() {
        stream.close();
    });
});

【问题讨论】:

  • 请将客户端和服务器代码发给我们,没有它你很难猜出你做错了什么!
  • 你能在服务器上抓包吗?
  • 简单的方法是在客户端使用 dataURL 翻录到 base64 并将该 b64 字符串发送到您将 atob(str.split(",")[1]) 写入文件的节点使用二进制模式(不是 uft8 或 base64)。如果你变得更硬核并且只需要支持更新的浏览器,你实际上可以使用 Socket.send() developer.mozilla.org/en-US/docs/Web/API/WebSocket#send() 发送一个未添加的二进制 blob
  • @user2448953 对于它的价值,您可以考虑使用 BinaryJS (github.com/binaryjs/binaryjs) 来设置您可以更轻松地读取/写入的流。其中一个示例包括完全按照您在此处所做的操作。
  • 同意布拉德的观点,binaryjs 做的完全一样。您正在尝试从头开始编写代码,然后对其进行调试。

标签: javascript html node.js file-upload websocket


【解决方案1】:

.readAsDataURL() 返回格式为 data:MIMEtype;base64,.... 的字符串 您应该删除逗号之前的部分,因为它不是 base64 编码文件的一部分,它是服务数据

【讨论】:

    【解决方案2】:

    考虑在 websocket 使用的不同端口上启动一个单独的 http 服务器,然后通过表单中的传统 post 操作上传文件。返回状态码 204(无内容)可确保浏览器在发布操作后不会挂起。服务器代码假定目录“上传”已经存在。这对我有用:

    客户

    <form method="post" enctype="multipart/form-data" action="http://localhost:8080/fileupload">
        <input name="filename" type="file">
        <input type="submit">
    </form>
    

    服务器

    http = require('http');
    formidable = require('formidable');
    fs = require('fs');
    
    http.createServer(function (req, res) {
    
        if (req.url === '/fileupload') {
    
            var form = new formidable.IncomingForm();
            form.parse(req, function (err, fields, files) {
                var prevpath = files.filename.path;
                var name = files.filename.name;
                var newpath = './upload/' + name;
    
                var is = fs.createReadStream(prevpath);
                var os = fs.createWriteStream(newpath);
    
                    // more robust than using fs.rename
                    // allows moving across different mounted filesystems
                is.pipe(os);
    
                    // removes the temporary file originally 
                    // created by the post action
                is.on('end',function() {
                    fs.unlinkSync(prevpath);
                });
    
                    // prevents browser from hanging, assuming
                    // success status/processing
                    // is handled by websocket based server code
                res.statusCode = 204;
                res.end();
    
            });
    
        }
    
    })
    .listen (8080);
    

    【讨论】:

    • 如果没有任何外部 nodejs 库,这将如何完成?
    【解决方案3】:

    当您在 nodejs 中流式传输数据时,您不使用 write(),而是使用 pipe()。 因此,一旦您像以前一样拥有写入流: var stream = fs.createWriteStream("file"); 然后你 pipe() 到它,如下所示: sourcestream.pipe(stream); 但是由于文件是通过 Internet 传输的,因此您的文件将以数据包的形式发送,因此它不会一次全部到达,而是分段到达,您必须使用缓冲区数组并手动计算数据块。

    您可以在此处了解详细信息: http://code.tutsplus.com/tutorials/how-to-create-a-resumable-video-uploade-in-node-js--net-25445

    还有一个可用的模块非常易于使用,并且可能是您想要的: https://github.com/nkzawa/socket.io-stream

    如果您不一定关心通过套接字,您也可以在客户端脚本中使用 ajax 表单 POST 使用服务器上的强大模块来处理表单上传:https://github.com/felixge/node-formidable

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-08
      • 2021-04-18
      • 2011-12-03
      • 2011-07-28
      • 1970-01-01
      • 1970-01-01
      • 2017-11-01
      • 1970-01-01
      相关资源
      最近更新 更多