JavaScript куча нехватки памяти |s3.getObject в приложении React / Node - PullRequest
2 голосов
/ 01 апреля 2019

У нас есть приложение React / Node, размещенное на Digital Ocean.Мы также используем пространства Digital Ocean, которые совместимы с AWS S3 для хранения объектов.По сути, приложение является своего рода внутренним Dropbox.У нас есть администраторы, которые могут создавать папки и загружать содержимое в эти папки.Затем у нас есть клиенты, которые могут войти в систему и загрузить любые файлы, доступ к которым им разрешен.

Мы успешно можем загрузить все файлы в Digital Ocean Spaces.Независимо от того, насколько они велики или малы.

Проблема в том, что когда мы пытаемся загрузить (как администратор или клиент) любой контент, размер которого превышает 100 МБ, у нас возникает ошибка кучи JavaScript в памяти.Эта ошибка появляется в Backend системы.

Вот некоторые решения, которые мы пытались администрировать:

  1. Предоставление ВМ с большим количеством оперативной памяти
  2. Увеличьтепамять браузера '--max-old-space-size'
  3. Включение Digital Ocean CDN для потоковой передачи контента через пограничные серверы
  4. Потоковая передача файловых данных на наш бэкэнд и их отправка на внешний интерфейс

Код внешнего интерфейса

downloadFile = (id, name, type) => {
axios
  .get(
    `/test-download/${id}`,
    this.props.handleSnackBar(
      "Your download has been started. Please wait."
    )
  )

  .then(res => {
    download(

      new Blob([new Uint8Array(res.data.data.Body.data)]),
      `${name}.${type}`
    );
    console.log(res);

    console.log(res.data.data.Body),
      this.props.handleSnackBar("Your download is now ready.");
  })
  .catch(err => console.log(err));
};

Код внутреннего интерфейса

app.get("/test-download/:id", (req, res) => {
var params = {
  Bucket: bucketName,
  Key: req.params.id
};

s3.getObject(params, function(err, data) {
  //
  console.log(data);
  //
  if (!err) {

    res.send({ data, key: params.Key });
  } else {
    console.log({ err }); // an error occurred
  }
});
});

Код внутреннего интерфейса с потоком

app.get("/test-download/:id", (req, res) => {
var params = {
  Bucket: bucketName,
  Key: req.params.id
};
// TRY

const fileRequest = s3.getObject(params);

let chunks = [];
fileRequest
  .createReadStream()

  .on("data", function(data) {
    console.log(`Received ${data.length} bytes of data`);
    chunks.push(data);
  })
  .on("end", function() {
    console.log("no more data");
    bufferData = Buffer.concat(chunks);
    console.log(bufferData);
    res.send({ bufferData, key: params.Key });
  });

});

Итак, в основном явроде застрял.Любая помощь, которая может быть предложена, очень ценится.Спасибо.

Ответы [ 2 ]

1 голос
/ 02 апреля 2019

Благодаря Маркосу я вновь посетил код трубопровода, который мы пытались. Но теперь, полностью понимая ответ на необработанные данные, который я получил от createReadStream().pipe(), я смог преобразовать данные.

Код интерфейса

app.get("/test-download/:id", (req, res) => {
var params = {
  Bucket: bucketName,
  Key: req.params.id
};

s3.getObject(params)
  .createReadStream()
  .pipe(res)
  .on("finish", () => {
    console.log("** done");
  });
});

Код сервера

downloadFile = (id, name, type) => {
axios
  .get(
    `/test-download/${id}`,
    { responseType: "arraybuffer" },
    this.props.handleSnackBar(
      "Your download has been started. Please wait."
    )
  )
  .then(res => {
    console.log(res);
    download(res.data, `${name}.${type}`);
    this.props.handleSnackBar("Your download is now ready.");
  })
  .catch(err => console.log(err));
};
1 голос
/ 02 апреля 2019

Проблема в том, что, когда вы используете streams в последнем фрагменте, вы буферизуете все чанки, отвергая цель использования потоков.

Вместо этого вы должны .pipe напрямую ответить, таким образом, используемая память будет довольно низкой.

app.get("/test-download/:id", (req, res) => {
    const params = {
        Bucket: bucketName,
        Key: req.params.id
    };

    s3.getObject(params)
        .createReadStream()
        .pipe(res);

});

Имейте в виду, что теперь вы не отвечаете на JSON объект, поэтому клиент должен быть изменен.

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