Какой оптимальный способ загрузки больших файлов на сервер с использованием NodeJS?

Как правильно загружать большие файлы на сервер (больше 1 ГБ), и какие варианты для этого существуют? Необходимо ли указывать лимит на 1 ГБ в конфигурации NGINX? Можно ли файл отправлять по частям и собирать на сервере? Как облачные хранилища загружают большие файлы на сервер?
  • 3 января 2024 г. 17:18
Ответы на вопрос 2
Для загрузки больших файлов на сервер необходимо учитывать ряд аспектов, чтобы процесс проходил эффективно и без потери данных. В Node.js существует несколько подходов к загрузке больших файлов:

1. **Потоковая загрузка файлов (Streaming)**
   
   Потоковая передача данных позволяет клиенту выгружать файлы на сервер по частям без необходимости загрузки файла целиком в память. Это существенно снижает риск исчерпания оперативной памяти на сервере. Модуль `fs` в Node.js предоставляет методы для чтения и записи файлов в потоковом режиме.

   Пример кода на Node.js:

   ```javascript
   const fs = require('fs');
   const http = require('http');

   const server = http.createServer((req, res) => {
     const filePath = './uploaded-file';
     const writableStream = fs.createWriteStream(filePath);

     req.pipe(writableStream);

     writableStream.on('finish', () => {
       res.writeHead(200, 'OK');
       res.end('File uploaded');
     });
   });

   server.listen(3000, () => console.log('Server is listening on port 3000'));
   ```

2. **Использование специализированных библиотек**

   Можно воспользоваться такими библиотеками, как `multer`, `busboy`, `formidable` и др., которые упрощают процесс загрузки файлов через HTTP, уже включая поддержку потоковой передачи данных.

3. **Загрузка файлов частями (Chunked Uploads)**

   Файл разбивается на множество мелких частей (chunks), которые затем загружаются на сервер поочерёдно. На серверной стороне эти части собираются обратно в исходный файл.

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

4. **Конфигурация прокси-сервера (NGINX)**

   Если перед вашим Node.js-сервером стоит прокси-сервер, такой как NGINX, вам действительно нужно учитывать его настройки, так как он может ограничивать максимальный размер тела запроса. Директива `client_max_body_size` в NGINX отвечает за максимально допустимый размер запроса, превышение которого приводит к ошибке `413 (Request Entity Too Large)`.

   Пример настройки для NGINX, чтобы разрешить загрузку больших файлов:

   ```
   http {
       ...
       server {
           ...
           client_max_body_size 2000M; # Установите значение, соответствующее вашим потребностям
           ...
       }
       ...
   }
   ```

5. **Обращение к API облачных хранилищ**

   Облачные хранилища, например, Amazon S3, Google Cloud Storage, реализуют свои механизмы для загрузки больших файлов, часто поддерживают загрузку частями (multipart upload). В таком случае на вашем сервере реализуется логика, которая выдает уникальные URL для загрузки файла, и клиент напрямую общается с облачным сервисом, минимизируя нагрузку на ваш сервер.

Для масштабируемости и надежности загрузки больших файлов, особенно если речь идет о сервисах
Я бы посмотрел в сторону как раз в сторону облачных хранилищ, например, в AWS S3 можно загружать файлы напрямую из браузера, для безопасности Ваш бакенд генерирует специальную ссылку (presigned URL) в которой можно настроить и время жизни ссылки и даже конкретный путь файла куда грузить чтоб кто попало что попало не грузил, тут можно почитать https://docs.aws.amazon.com/AmazonS3/latest/usergu... 
Браузер хром поможет с переводом.
Удачи

PS особенно актуально если файлы надо не только грузить но еще и потом раздавать, при большой нагрузке сеть на одной машине может стать узким горлышком, придется масштабировать сервер с NGINX, но если только загружать фаылй на сервер, то можно без S3
Похожие вопросы