Невозможно загрузить большие файлы с помощью nodejs / axios

#node.js #axios

#node.js #axios

Вопрос:

Я пишу клиент nodejs, который будет загружать файлы (файлы могут быть как двоичными, так и текстовыми файлами) с моего локального компьютера разработчика на мой сервер, написанный на Java, настройка которого невозможна. Я использую следующий код для загрузки файлов, он отлично работает для файлов объемом до 2 ГБ, но помимо этого выдает ошибку, указанную ниже. Теперь вы можете подумать, что сервер может не разрешать файлы объемом более 2 ГБ, но я успешно загрузил файлы объемом до 10 ГБ, используя Rest-клиенты, такие как Postman и Insomnia, в том же экземпляре.

 const fs = require("fs");
const path = require("path");
const axios = require("axios");
const FormData = require("form-data");

function uploadAxios({ filePath }) {
  
let formData;
try {
  formData = new FormData();
  formData.append("filedata", fs.createReadStream(filePath));
} catch (e) {
  console.error(e)
}

  axios
    .post(
      `https://myinstance.com`,
      formData,
      {
        headers: {
          ...formData.getHeaders(),
          "Content-Type": "multipart/form-data",
          Authorization:
            "Basic xyz==",
        },
        maxContentLength: Infinity,
        maxBodyLength: Infinity,
        // maxContentLength: 21474836480,
        // maxBodyLength: 21474836480, // I have tried setting these values with both numbers and the keyword Infinity but nothing works
      }
    )
    .then(console.log)
    .catch(console.error);
}

const filePath = "C:\Users\phantom007\Documents\BigFiles\3gb.txt";
 
uploadAxios({  filePath  });
  

Ошибка, которую я получаю:

 #
# Fatal error in , line 0
# API fatal error handler returned after process out of memory
#

<--- Last few GCs --->
es[7844:0000023DC49CE190]    47061 ms: Mark-sweep 33.8 (41.8) -> 33.8 (41.8) MB, 417.2 / 0.1 ms  (  947.1 ms in 34029 steps since start of marking, biggest step 431.0 ms, walltime since start of marking 15184 ms) finalize incremental marking via stack guard[7844:0000023D
C49CE190]    48358 ms: Mark-sweep 34.4 (41.8) -> 31.8 (40.5) MB, 1048.4 / 0.0 ms  (  0.0 ms in 1 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 1049 ms) finalize incremental marking via task GC in old spac

<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 000002E294C255E9 <JSObject>
    0: builtin exit frame: new ArrayBuffer(aka ArrayBuffer)(this=0000022FFFF822D1 <undefined>,65536)

    1: _read [fs.js:~2078] [pc=0000004AD942D301](this=0000039E67337641 <ReadStream map = 000002F26D804989>,n=65536)
    2: read [_stream_readable.js:454] [bytecode=000002A16EB59689 offset=357](this=0000039E67337641 <ReadStream map = 000002F26D804989>,n=0)
    3: push [_stream_readable.js:~201]...

FATAL ERROR: Committing semi space failed. Allocation failed - process out of memory
  

Похоже, ошибка связана с тем, что она превысила лимит памяти, я знаю, что, передав флаг —max-old-space-size, я могу преодолеть это, но я хочу, чтобы это было масштабируемым, а не жестко задавало верхний предел.

PS: На моем компьютере для разработчиков 12 ГБ свободной памяти

Редактировать: я добавил трассировку ошибок.

Комментарии:

1. Вы регистрировали, где произошел сбой, то есть FormData.append, FormData.getHeaders() или axios.post?

2. Я могу отправить файл объемом 4 ГБ на локальный сервер Express / Multer с вашим кодом. Кажется, не имеет никакого значения, использую ли я предел 21474836480 или Бесконечность. Оба работают, так что должно быть что-то еще, вызывающее проблему. Вы пытались изменить время ожидания? например, тайм-аут: xxx, это немного рискованно, хотя!

3. @Pavlo Вы были правы, я завернул FormData в try catch и получил ошибку (я отредактировал свой пост и добавил ошибку).

4. @TerryLennox Я получил ошибку и вставил ее в свой оригинальный пост. Похоже, это проблема с нехваткой памяти. И теперь я хочу, чтобы он был масштабируемым, т. Е. Не фиксировал верхний предел памяти. Пожалуйста, предложите

5. Ну, это сильно сужает кругозор. Я попытаюсь воспроизвести ошибку!

Ответ №1:

Я использую multer для определения предела, смотрите Следующий код:

   app.use(multer({
  storage: storage,
  dest: path.join(pathApp),
  limits: {
    fileSize: 5000000
  },
  fileFilter: function fileFilter(req, file, cb) {
    var filetypes = /json/;
    var mimetype = filetypes.test(file.mimetype);
    var extname = filetypes.test(path.extname(file.originalname));

    if (mimetype amp;amp; extname) {
      console.log("Port ".concat(app.get('port'))   " - Uploading file "   file.originalname);
      return cb(null, true, req);
    }

    cb(JSON.stringify({
      "success": false,
      "payload": {
        "app": "upload",
        "function": "upload"
      },
      "error": {
        "code": 415,
        "message": 'File type not valid'
      }
    }));
  }
}).single('file1'));