Загрузка файлов через socket.io (JavaScript & FileReader) - PullRequest
0 голосов
/ 19 января 2020

Я создаю приложение для чата (в React Native), но сейчас я провел несколько тестов на vanilla JavaScript. Сервер является NodeJS -сервером.

Он работает с отправкой текстовых сообщений, но теперь у меня есть несколько вопросов об отправке фото / видео / аудио файлов. Я провожу много исследований в Интернете о том, как лучше всего это сделать.

Мне пришла в голову идея использовать API-интерфейс FileReader, разделить файл на куски и отправлять куски по частям через socket.emit () - функция.

Это мой код (упрощенно):

Обратите внимание, что я создам приложение React Native, но пока (для тестирования ), Я только что создал HTML -файл с формой загрузки.

// index.html
// the page where my upload form is

var reader = {};
var file = {};
var sliceSize = 1000 * 1024;
var socket = io('http://localhost:8080');

const startUpload = e => {
    e.preventDefault();
    reader = new FileReader();
    file = $('#file)[0].files[0]
    uploadFile(0)
}

$('#start-upload').on('click', startUpload)

const uploadFile = start => {
    var slice = start + sliceSize + 1;
    var blob = file.slice(start, slice)
    reader.on('loadend', e => {
        if (slice < file.size) {
            socket.emit('message', JSON.stringify({
                fileName: file.name,
                fileType: file.type,
                fileChunk: e.target.result
            })
        } else {
            console.log('Upload completed!')
        }
    })
    reader.readAsDataURl(blob) 
}

// app.js
// my NodeJS server-file

var file;
var files = {};

io.on('connection', socket => {
    console.log('User connected!');

    // when a message is received
    socket.on('message', data => {
        file = JSON.parse(data)
        if (!files[file.fileName]) {
            // this is the first chunk received
            // create a new string
            files[file.fileName] = '';
        }
        // append the binary data
        files[file.fileName] = files[file.fileName] + file.fileChunk;
    })

    // on disconnect
    socket.on('disconnect', () => {
        console.log('User disconnected!');
    })
})

Я не включал какие-либо проверки для типа файла (я еще не на этом этапе), Сначала я хочу убедиться, что это правильно.

Материал, который мне нужно сделать:

  • Отправить сообщение (например, socket.emit ('uploaddone',. ..)) от клиента к серверу, чтобы уведомить сервер о том, что загрузка завершена (и сервер может передать весь файл другому пользователю).

Мои вопросы:

  • Можно ли отправлять порции двоичных данных (base64) через сокет, или это займет много трафика?
  • Wi Потеряю ли я качество (фото / видео / аудиофайлы) при разбиении их на куски?

Если есть лучший способ сделать это, пожалуйста, дайте мне знать. Я не прошу рабочие примеры кода, просто некоторые указания в хорошем направлении.

1 Ответ

1 голос
/ 19 января 2020

Вы можете отправлять необработанные байты через WebSocket, base64 имеет размер накладных расходов 33%.

Также вам не нужно будет JSON .stringify всего (и, возможно, большого) тела и анализировать его на стороне клиента .

Потеряю ли я качество

Нет, базовый протокол (TCP) доставляет данные в порядке и без повреждения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...