Потоковая передача файла из браузера на сервер Express - PullRequest
0 голосов
/ 25 сентября 2018

Я пытаюсь загрузить файлы, которые пользователь выбирает в браузере, на сервер Express.Я хочу потоковую передачу файлов, чтобы их не нужно было загружать в память перед их загрузкой.

Приведенный ниже код работает нормально и файлы загружаются.Однако запрос к серверу фактически не отправляется, пока не будет обработан весь файл.Если я отправлю файл размером 100 МБ, потребуется несколько секунд, чтобы индикатор выполнения полностью заполнился, и только тогда запрос поступит на сервер.Если я загружаю большие файлы, происходит сбой браузера.

Если я запускаю тот же код, меняя только ввод на fs.CreateReadStream и удаляя биты React с узлом, он работает как положено, и файл передается в потоковом режиме.

Почему это не работает в браузере и как я могу заставить его работать?

Серверная часть очень проста и отлично работает:

router.put("/*", (req, res, next) => {
  console.log("Starting to receive file");
  const dst = fs.createWriteStream(fileRoot + req.params[0]);
  console.log("Created file write stream");
  req.pipe(dst);
  req.on("end", () => {
    console.log("Upload complete");
    res.send("Upload complete");
  });
});

Код на стороне клиента выглядит следующим образом:

sendFiles() {
    const queue = [].concat(this.state.files);
    let sizeSent = 0;
    let fileSize = 0;
    const that = this;

    const reportProgress = new Transform({
      transform(chunk, encoding, callback) {
        sizeSent += chunk.length;
        that.setState({ progress: (200 / fileSize) * sizeSent });
        callback(null, chunk);
      }
    });

    function sendNext() {
      that.setState({ progress: 0 });
      sizeSent = 0;
      const currentFile = queue.shift();
      fileSize = currentFile.size;
      const hash = crypto.createHash("md5");
      const hashedName = hash.update(currentFile.name).digest("hex");
      console.log("sending file " + currentFile.name);
      new FileReadStream(currentFile)
        .pipe(crypto.createCipher("aes128", "test"))
        .pipe(reportProgress)
        .pipe(
          request({
            url: "http://localhost:8000/files/send/" + hashedName,
            method: "put"
          })
        )
        .on("error", err => {
          console.log(err);
        })
        .on("end", function(file) {
          console.log("Done");
          if (queue.length > 0) {
            sendNext();
          } else {
            that.setState({ progress: 200 });
          }
        });
    }    
    sendNext();
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...