Загрузите большой файл (видео) на сервер nodejs и aws s3 с помощью ReactJs

Я работаю над созданием платформы OTT, но столкнулся с проблемой загрузки большого файла на сервер. Я попытался сделать это с помощью multer, чтобы сохранить файл во временной папке и использовать aws-sdk s3.upload. Он отлично работает с небольшим размером файла, но если я попытаюсь загрузить большой файл, он вернется

Ошибка сети или объект запроса ошибки 413 слишком велик

После ошибки 413 — я изменил nginx.config (client_max_body_size 0;)

// 0 для неограниченного

но до сих пор без изменений. Я также пытался сделать это с помощью multer-s3, но безуспешно. Позже я попытался сделать это с официантом, но все же столкнулся с той же проблемой. Здесь я прикрепляю свой код, где я использую busboy В ReactJs я использую Axios Пожалуйста, помогите

сервер.js

const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const passport = require('passport');
const helmet = require('helmet');
const path = require('path');
const morgan = require('morgan');
const cors = require('cors');
const dotenv = require('dotenv');
// var admin = require('firebase-admin');
const rateLimit = require('express-rate-limit');
const busboy = require('connect-busboy');




const { setCloudinary } = require('./middleware/cloudinary');
// initalizing app
const app = express();

app.use(cors());
// app.use(helmet());
app.use(
  busboy({
    highWaterMark: 10 * 1024 * 1024, // Set 10 MiB buffer
  })
); // Insert the busboy middle-ware

// for environment files
if (process.env.NODE_ENV === 'production') {
  dotenv.config({ path: './env/.env.production' });
} else {
  dotenv.config({ path: './env/.env' });
}

const PORT = process.env.PORT || 5000;
const mongoDbUrl = process.env.mongoDbUrl;

const profileRoute = require('./routes/profile');
const adminRoute = require('./routes/admin');
const planRoute = require('./routes/plan');
const videoRoute = require('./routes/video');

//connnecting mongoDB server
mongoose
  .connect(mongoDbUrl, {
    useNewUrlParser: true,
    useFindAndModify: false,
    useCreateIndex: true,
    useUnifiedTopology: true,
  })
  .then((result) => {
    if (result) {
      setCloudinary();
      //if all goes right then listing to the server
      // var server = https.createServer(options, app);
      // console.log(server);
      app.listen(PORT, (err) => {
        if (err) throw err;
        console.log(`server is running at ${PORT}`);
      });
    }
  })
  .catch((err) => {
    throw err;
  });

//logging logs
if (process.env.NODE_ENV === 'production') {
  app.use(morgan('tiny'));
} else {
  app.use(morgan('dev'));
  mongoose.set('debug', true);
}

//initiallizaing passport
app.use(passport.initialize());
// require('./utils/adminRole')(passport);
require('./utils/firebase');
require('./utils/gcm');

app.use(express.json());
app.use(
  express.urlencoded({
    extended: true,
  })
);

// API serving routes
app.use('/api/v1/profile', profileRoute);
app.use('/api/v1/admin', adminRoute);
app.use('/api/v1/plan', planRoute);
app.use('/api/v1/videos', videoRoute);
// FOR REACT JS APP
//if the app is in production then serve files also
// if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test') {
app.use(express.static(path.join(__dirname, 'client', 'build')));
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'client', 'build', 'index.html'));
});
// }

// task

require('./jobs/Jobs');

router.js

router.post('/add/video', (req, res) => {
  req.pipe(req.busboy); // Pipe it trough busboy

  req.busboy.on('file', (fieldname = 'video', file, filename) => {
    console.log(`Upload of '${filename}' started`);

    // Create a write stream of the new file
    const fstream = fs.createWriteStream(path.join('temp/', filename));
    // Pipe it trough
    file.pipe(fstream);

    // On finish of the upload
    fstream.on('close', () => {
      console.log(`Upload of '${filename}' finished`);

      const childProcess = fork('./processVideo.js', ['message']);
      childProcess.on('message', (msg) => res.send(msg));
      childProcess.send({ file: fstream, data: req.body });
    });
  });
});

В ReactJs я использую Axios

 const config = {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
      onUploadProgress: function (progressEvent) {
        var percentCompleted = Math.round(
          (progressEvent.loaded * 100) / progressEvent.total
        );
        console.log(percentCompleted);
      },
    };
    const formData = new FormData();
    formData.append('video', selectedVideo);
    formData.append('title', title);
    formData.append('description', description);
    formData.append('movieCategory', movieCategory);
    formData.append('thumbnail', thumbnail);
    formData.append('price', price);
    formData.append('isPremium', isPremium);
    formData.append('quality', quality);
    formData.append('language', language);
    formData.append('releaseYear', releaseYear);
    formData.append('duration', duration);

    axios
      .post('/api/v1/admin/add/video', formData, config)
      .then((res) => {
        console.log(res);
        alert('File Upload success');
      })
      .catch((err) => {
        console.log(err);
        alert('File Upload Error');
      });

person kvadityaaz    schedule 02.05.2021    source источник


Ответы (4)


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

person Anton Iskryzhytskyi    schedule 02.05.2021
comment
Спасибо за вашу помощь, но я хотел загрузить его на сервер, а затем загрузить на s3. Решено с помощью многопоточной загрузки файлов. - person kvadityaaz; 07.05.2021

Пробовали ли вы использовать многочастную загрузку S3 или потенциально ускорение переносаr ?

person Jack Marchetti    schedule 02.05.2021
comment
Спасибо за вашу помощь, но я хотел загрузить его на сервер, а затем загрузить на s3. Решено с помощью многопоточной загрузки файлов. - person kvadityaaz; 07.05.2021

Я вижу, вы используете Express. Вам необходимо установить предельный размер экспресс-запроса. Значение по умолчанию — 100kb.

app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ limit: '50mb', extended: true }));

Кроме того, Multer также имеет ограничение размера файла по умолчанию, равное 1mb, поэтому попробуйте изменить и это:

const video_upload = multer({ 
  storage: videoStorage,
  fileFilter: videoFilter,
  limits: {
     fieldSize: '50mb'
  }
});
person Nenad Milosavljevic    schedule 02.05.2021
comment
Спасибо, я хотел загрузить файл размером около 3-4 ГБ. Решено с помощью многопоточной загрузки файлов. - person kvadityaaz; 07.05.2021

Я решил проблему с помощью многопоточной загрузки файлов. Об этом можно прочитать в блоге. Здесь

person kvadityaaz    schedule 07.05.2021