POST multipart / form-data в Serverless Next. js API (работает на Vercel / Now. sh) - PullRequest
0 голосов
/ 16 июня 2020

Я использую функцию Vercel Serverless для обработки загрузки файла в Digital Ocean Spaces (API идентичен AWS S3). Однако у меня возникают проблемы с обработкой multipart / form-data в обработчике запросов.

Во внешнем интерфейсе я использую fetch для публикации объекта FormData () с файлами и парой текстовых полей. При регистрации тела и серверов в заголовке я вижу там все, как ожидалось, однако при обработке multipart с Multer (я также пробовал пару других подобных пакетов) я не могу получить ни одно из опубликованных полей или файлов .

Также стоит отметить, что при использовании Postman для проверки запросов POST я сталкиваюсь с той же проблемой, поэтому я уверен, что проблема заключается в бессерверной функции.

Front -end:

const handleSubmit = async (values) => {
    const formData = new FormData();

    // build my Form Data from state.
    Object.keys(values).forEach(key => {
      formData.append(key, values[key]);
    });

    const response = await fetch("/api/post-submission", {
      method: "POST",
      headers: {
        Accept: "application/json",
      },
      body: formData,
    });
    const json = await response.json();
  };

Бессерверный обработчик:

const util = require("util");
const multer = require("multer");

module.exports = async (req, res) => {
  await util.promisify(multer().any())(req, res);
  console.log("req.body", req.body); // >> req.body [Object: null prototype] {}
  console.log("req.files", req.files); // >> req.files []

  // Do the file upload to S3...

  res.status(200).json({ uploadData });
};

Ожидаемое поведение:

req.body и req.files должны быть заполнены моими отправленными данными.

Ответы [ 3 ]

2 голосов
/ 28 июля 2020

Я не совсем уверен насчет пакета Multer, но нет никаких присущих ему ограничений, которые мешают обработке multipart / form-data бессерверными функциями на Vercel (AWS Lambda под капотом).

let multiparty = require('multiparty')
let http = require('http')
let util = require('util')

module.exports = (req, res) => {
    if (req.method === "POST") {
        let form = new multiparty.Form();
        form.parse(req, (err, fields, files) => {
            res.writeHead(200, { 'content-type': 'text/plain' });
            res.write('received upload: \n\n');
            res.end(util.inspect({ fields: fields, files: files }));
        });
        return;
    } else {
        res.writeHead(405, { 'content-type': 'text/plain' });
        res.end("Method not allowed. Send a POST request.");
        return;
    }
}

Я создал демонстрационный репозиторий с развернутым URL здесь

1 голос
/ 30 июля 2020

Мне удалось заставить multipart/form-data работать, используя busboy .

const Busboy = require('busboy');

module.exports = (req, res) => {
    const busboy = new Busboy({ headers: req.headers });

    busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
      console.log('File [' + fieldname + ']: filename: ' + filename);

      file.on('data', function(data) {
        console.log('File [' + fieldname + '] got ' + data.length + ' bytes');
      });

      file.on('end', function() {
        console.log('File [' + fieldname + '] Finished');
      });
    });

    busboy.on('field', function(fieldname, val, fieldnameTruncated, valTruncated) {
      console.log('Field [' + fieldname + ']: value: ' + val);
    });

    busboy.on('finish', function() {
      console.log('Done parsing form!');
      res.writeHead(303, { Connection: 'close', Location: '/' });
      res.end();
    });

    req.pipe(busboy);
}
0 голосов
/ 22 июля 2020

Серверы бессерверных функций в службе vercel нуждаются в файле конфигурации (vercel. json) с маршрутами для работы, если вам нужно увидеть, как работают маршруты: https://vercel.com/docs/configuration#project / routes

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

{
  "routes" : [
    {"src":"/api/post-submission", "methods": ["POST"], "dest": "<js file>"}
  ]
}
...