Загрузка файлов с помощью Websockets и Nodejs

Я пытаюсь реализовать загрузчик файлов, где HTML файл отправляется WebSocket на сервер Nodejs.

Пытался прочитать файл в BLOB и двоичную строку из API FileReader HTML и отправил его на сервер Nodejs, чтобы он мог быть записан в файл на сервере. Пробовал createWriteStream и writeFile с кодировкой ascii или base 64 в части Nodejs.

Тем не менее файл, сохраненный на сервере, работает неправильно.

Я что-то пропустил?

Спасибо

ОБНОВЛЕНИЕ

Client

    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();
    });
});

Ответ 1

.readAsDataURL() возвращает строку в формате данных: MIMEtype; base64,.... вы должны удалить часть перед запятой, так как она не является частью файла с кодировкой base64, это служебные данные

Ответ 2

Когда вы передаете данные в nodejs, вы не используете write(), а вместо этого используете pipe(). Итак, как только у вас есть свой поток записи, как и вы: var stream = fs.createWriteStream( "файл" ); то вы используете pipe() для него, как в: sourcestream.pipe(stream); Но поскольку файл передается через Интернет, ваш файл будет отправлен в пакетах, и поэтому он не будет поступать сразу, а вместо этого на куски, вы должны использовать буферный массив и вручную подсчитывать куски данных.

Вы можете узнать подробности здесь: http://code.tutsplus.com/tutorials/how-to-create-a-resumable-video-uploade-in-node-js--net-25445

Имеется также доступный модуль, который очень прост в использовании и, вероятно, что вы хотите: https://github.com/nkzawa/socket.io-stream

Если вы не заботились о том, чтобы переходить через сокет, вы также можете сделать это в своих клиентских сценариях с помощью формы POST ajax с помощью грозного модуля на сервере для обработки загрузки формы: https://github.com/felixge/node-formidable

Ответ 3

Рассмотрите возможность запуска отдельного http-сервера на другом порту, используемом веб-сайтом, и затем загрузите файл через традиционное почтовое действие в форме. Возвращаемый код статуса 204 (без содержимого) гарантирует, что браузер не будет висеть после действия post. Код сервера предполагает, что каталог "upload" уже существует. Это сработало для меня:

Client

<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);