【问题标题】:POST multipart/form-data to Serverless Next.js API (running on Vercel / Now.sh)将 multipart/form-data 发布到无服务器 Next.js API(在 Vercel / Now.sh 上运行)
【发布时间】:2020-10-06 05:38:21
【问题描述】:

我正在使用 Vercel 无服务器函数来处理上传到 Digital Ocean Spaces 的文件(与 AWS S3 相同的 API)。但是,我遇到了在请求处理程序中处理 multipart/form-data 的问题。

在前端,我使用 fetch 发布带有文件和几个文本字段的 FormData() 对象。在标题上记录正文和服务器时,我可以按预期看到那里的所有内容,但是在使用 Multer 处理多部分时(我还尝试了其他几个类似的包)我无法检索任何已发布的字段或文件.

另外值得注意的是,在使用 Postman 测试 POST 请求时,我遇到了完全相同的问题,因此我确信问题在于无服务器功能。

前端:

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 应该填充我提交的数据。

【问题讨论】:

  • 您可以尝试生成一个预签名 URL 并将其提供给客户端以将文件直接上传到 S3,从而跳过无服务器功能
  • @Jack-wild 你解决了吗?
  • @T.Vojtech 恐怕不行——Vercel 帮助团队要求我提供一份复制品,但我还没有收到他们的回复。在 Vercel 上使用 next.js 似乎确实是一个错误(如果您直接在 Vercel 上运行无服务器函数,它们可以正常工作,但是当您还使用 Next.js 时,即使代码相同,它们也不会)

标签: node.js forms multipartform-data serverless vercel


【解决方案1】:

我看到你使用form-data,你可以将标题内容类型设置为multipart/form-data;boundary=----WebKitFormBoundaryyrV7KO0BoCBuDbTL

【讨论】:

    【解决方案2】:

    vercel 服务上的无服务器功能服务器需要一个带有路由的配置文件 (vercel.json) 才能工作,如果您需要查看路由是如何工作的:https://vercel.com/docs/configuration#project/routes

    配置文件将帮助您将传入的 post 请求重定向到您的 js 文件。例如:

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

    【讨论】:

    • 我认为这个建议可能已经过时了,因为如果你这样命名路线,它们会自动工作。问题实际上是 Vercel 无服务器函数不支持多部分数据
    • @Jack,那么如何在 vercel 中发布到无服务器 fns?如果您无法将表单数据发布到服务器,那么这种无服务器业务如何可行?
    【解决方案3】:

    我能够使用busboymultipart/form-data 工作。

    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);
    }
    

    【讨论】:

      【解决方案4】:

      我不太确定 Multer 包,但没有任何固有限制会阻止 Vercel 上的无服务器函数(AWS Lambda 底层)处理 multipart/form-data。

      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 here 创建了一个演示存储库

      【讨论】:

      • 谢谢——这真的很有帮助,我会试试看。也许你是对的并且它是受支持的,但是当我问 Vercel 支持人员时说 multipart 不受支持(他们可能只是被误导了)。可能是爱好帐户不支持它。
      • 哦,刚刚看到您 Vercel 支持团队! ? 我猜我说话的人是错误的,或者可能是过时的信息。
      • ——我做了一些调试和测试,在 next.js 框架中运行 API 函数时似乎不支持多部分表单数据——仅当部署为独立的无服务器函数时韦尔塞尔。是否有这种情况的原因,是否有任何方法可以改变这种情况,以便它们将在 next.js 中运行
      猜你喜欢
      • 1970-01-01
      • 2019-01-06
      • 1970-01-01
      • 2018-12-31
      • 1970-01-01
      • 1970-01-01
      • 2018-08-06
      • 2016-11-14
      • 1970-01-01
      相关资源
      最近更新 更多