Обработка ошибок при загрузке файла с использованием multer с expressjs

Я использую multer, чтобы сохранить файл на сервере, разработанном через express & nodejs.

Я использую следующий код.

var express = require('express'),
    multer  = require('multer')

var app = express()

app.get('/', function(req, res){
  res.send('hello world');
});

app.post('/upload',[ multer({ dest: './uploads/'}), function(req, res){

    res.status(204).end()
}]);

app.listen(3000);

Малтер сохраняет файл для меня в указанной папке назначения.

Все это работает нормально, но у меня есть следующие вопросы:

  1. Если сохранение файла не удается по разным причинам, похоже, мой маршрут всегда вернет статус 204.
  2. Я не уверен, что статус 204 восстанавливается после сохранения файла или во время асинхронного сохранения файла возвращается статус 204.

9 ответов

Решение

Вы можете обрабатывать ошибки, используя onError опция:

app.post('/upload',[
  multer({
    dest    : './uploads/',
    onError : function(err, next) {
      console.log('error', err);
      next(err);
    }
  }),
  function(req, res) {
    res.status(204).end();
  }
]);

Если вы позвоните next(err) ваш обработчик маршрута (генерирующий 204) будет пропущен, а ошибка будет обработана Express.

Я думаю (не уверен на 100%, так как это зависит от того, как multer что ваш обработчик маршрута будет вызван при сохранении файла. Ты можешь использовать onFileUploadComplete зарегистрировать сообщение, когда загрузка будет завершена, и сравнить его с вызовом вашего обработчика маршрута.

Глядя на код, multer вызывает следующий обработчик промежуточного программного обеспечения / маршрута, когда файл полностью загружен.

Вот как можно написать многоуровневое промежуточное ПО, которое обрабатывает загрузку и ошибки

const multer = require("multer");

function uploadFile(req, res, next) {
    const upload = multer().single('yourFileNameHere');

    upload(req, res, function (err) {
        if (err instanceof multer.MulterError) {
            // A Multer error occurred when uploading.
        } else if (err) {
            // An unknown error occurred when uploading.
        }
        // Everything went fine. 
        next()
    })
}

Попробуй это

var upload = multer().single('avatar')

app.post('/profile', function (req, res) {
  upload(req, res, function (err) {
    if (err) {
      // An error occurred when uploading 
      return
    }

    // Everything went fine 
  })
}

ссылка:

http://wiki.workassis.com/nodejs-express-get-post-multipart-request-handling-example/

https://www.npmjs.com/package/multer

Я думаю, что лучший способ — обработка ошибок с помощью промежуточного программного обеспечения.

      const multerErrorHandling = (err, req, res, next) => {
if (err instanceof multer.MulterError) {
  res.status(400).send("Multer error: " + err.message);
} else {
  next();
}
};
  // you should use after multer to send another respond.
  app.post("/upload", singleUpload,multerErrorHandling,(req, res) => {
      var multer = require('multer')
var upload = multer().single('avatar')
 
app.post('/profile', function (req, res) {
  upload(req, res, function (err) {
    if (err instanceof multer.MulterError) {
      handle error
    } else if (err) {
      handle error
    }
    else{
      write you code
    }
  })
})


you can see this from the [documentation][1]


  [1]: https://www.npmjs.com/package/multer#error-handling

Как видно из приведенного ниже кода (источник из файла muter index.js), если вы не передадите обратный вызов onError, ошибка будет обработана Express.

    fileStream.on('error', function(error) {
      // trigger "file error" event
      if (options.onError) { options.onError(error, next); }
      else next(error);
    });

Согласно документации multer ( https://github.com/expressjs/multer#error-handling)

Обработка ошибок

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

Если вы хотите ловить ошибки именно из Multer, вы можете самостоятельно вызвать функцию промежуточного программного обеспечения. Кроме того, если вы хотите перехватывать только ошибки Multer, вы можете использовать класс MulterError, присоединенный к самому объекту multer (например, err instanceof multer.MulterError).

образец кода

          const multer = require('multer')
   const upload = multer().single('avatar')
   
   app.post('/profile', function (req, res) {
     upload(req, res, function (err) {
       if (err instanceof multer.MulterError) {
         // A Multer error occurred when uploading.
       } else if (err) {
         // An unknown error occurred when uploading.
       }
   
       // Everything went fine.
     })
   })

Когда мы перепишем код в этом вопросе с последней версией multer (v1.4.5-lts.1)

      const express = require('express');

const multer = require('multer');

const app = express();

const upload = multer({ dest: './uploads/' }).single('fieldName');

app.get('/', (req, res) => {
    res.send('hello world');
});

app.post(
    '/upload',
    (req, res, next) => {
        upload(req, res, (err) => {
            if (err instanceof multer.MulterError) {
                res.status(404).send(err + 'Upload failed due to multer error');
            } else if (err) {
                res.status(404).send(err + 'Upload failed due to unknown error');
            }
            // Everything went fine.
            next();
        });
    },
    (req, res) => {
        res.status(204).end();
    }
);

app.listen(3000);

Чтобы проверить ошибки Multer и ошибки, не связанные с multer, мы можем добавить проверки, используя fileFilter и ограничения, например: я добавляю метод фильтрации файлов CSV и некоторые ограничения.

      // CSV file filter - will only accept files with .csv extension
const csvFilter = (req, file, cb) => {
    console.log('csv filter working');
    if (file.mimetype.includes('csv')) {
        cb(null, true);
    } else {
        cb('Please upload only csv file.', false);
    }
};

// adding the csv file checking, file number limit to 1 and file size limit 10 1kb
const upload = multer({
    dest: './uploads/',
    fileFilter: csvFilter,
    limits: { files: 1, fileSize: 1024 } 
}).single('fieldName');

Мы можем видеть различные ошибки, возникающие, когда мы пытаемся загрузить файл, отличный от CSV, или файл размером> 1 КБ, или несколько файлов.

Будьте осторожны с системой, когда пользователь что-либо вам отправляет

Я обычно устанавливаю больше [*option1]:

process.on('uncaughtException', function(ls){
  // console.log(ls);
  (function(){})();
});

А потом:

var upload= multer({ dest: __dirname + '/../uploads/' }).single('photos');
// middle ..
upload(req, res, function (err) {
  if (err instanceof multer.MulterError) {
    // A Multer error occurred when uploading.
    console.log('MulterError', err);
  } else if (err) {
    // An unknown error occurred when uploading.
    // Work best when have [*option1]
    console.log('UnhandledError', err);
  }
  if(err) {
    return res.sendStatus(403);
  }
  res.sendStatus(200);
});

пакет: "multer": "^1.4.2"

Я знаю, что уже поздно, но это может помочь другим.

Вот как я обрабатываю ошибки и безопасно использую это в своем проекте экспресс/машинописи.

      const upload = (fieldName: string) => {
  return (req: Request, res: Response, next: NextFunction) => {
    return multer({
      storage: multer.diskStorage({
        destination: (req, file, cb) => {
          if (file.fieldname === 'post') {
            return cb(null, `${path.join(path.dirname(__dirname), 'uploads/postImg')}`);
          } else if (file.fieldname === 'profile') {
            return cb(null, `${path.join(path.dirname(__dirname), 'uploads/ProfilePic')}`);
          } else {
            return cb(new Error(`${file.fieldname} is incorrect`), null);
          }
        },
        filename: (req, file, cb) => {
          return cb(null, `${file.originalname}-${Date.now()}-${file.fieldname}`);
        },
      }),
      fileFilter: (req, file, cb) => {
        const fileExtension = file.mimetype.split('/')[1];
        if (!(fileExtension in allowedFiles)) return cb(null, false);
        return cb(null, true);
      },
      dest: `${path.join(path.dirname(__dirname), 'uploads')}`,
      limits: {
        fileSize: 1024 * 1024 * 3, // 3MB
        files: 1,
      },
    }).single(fieldName)(req, res, (err: any) => {
      if (err instanceof multer.MulterError) {
        // handle file size error
        if (err.code === 'LIMIT_FILE_SIZE') return res.status(400).send({ error: err.message });
        // handle unexpected file error
        if (err.code === 'LIMIT_UNEXPECTED_FILE') return res.status(400).send({ error: err.message });
        // handle unexpected field key error
        if (err.code === 'LIMIT_FIELD_KEY') return res.status(400).send({ error: err.message });
      }
      next();
    });
  };
};




app.post("/upload", (req: Request, res:Response)=>{
res.json({message:"file uploaded"})
})
Другие вопросы по тегам