Post FormData 在 Heroku 上使用 Multer - 503 获取空“req.files”

问题描述 投票:0回答:2

我必须先从

client --> server1 
上传文件,然后从
server1 --> server2
上传。

注意:我知道我不应该将文件存储在heroku中,但实际上我不需要 要存储文件,我只需要它临时来制作一些 修改,然后将其传递给第二个服务,就可以了 其他修改。例如,让我们考虑 2 个微服务,其中一个 调整大小,一压缩。只是作为例子。无论如何,在这一步,我只是通过 文件不做任何修改。 无论如何,我也尝试过

multer-s3
但这是同样的问题。

我在 Heroku 上部署的两台节点服务器上都使用

multer
。 我在 server1 上成功接收文件。当我将文件发送到 server2 时,heroku 上升:

  • server2
at=warning code=H28 desc="Client Connection Idle" method=POST 
BadRequestError: request aborted app[web.1]:     at IncomingMessage.onAborted 
  • server1
code=H12 desc="Request timeout"

server1
,我以这种方式接收文件

/* ==============================
    UPLOAD MIDDLEWARE
============================== */
const multer  = require('multer');
let multer_storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, `${__dirname}/my_uploads`); // <-- be sure this dir already exists, otherwise create it
  }
});

const form_upload = multer({  storage : multer_storage,
                              cb(null, true); }  });

/* ==============================
API ROUTE
============================== */
app.post('/server1/files', 
                  function(req, res)
 {
            
  form_upload.fields([{ name: 'file1' }, { name: 'file2' }])(req, res, (err, body) => {
   // req.files contains file1 and file2 uploaded
   var file1 = req.files["file1"][0];
   var file2 = req.files["file2"][0];
   ...
}

然后,一直在

server1
,我以这种方式将这些文件发送到
server2

const FormData = require('form-data');
const fs = require('fs'); 

const form = new FormData();
form.append("file1", fs.createReadStream(file1.path), file1.originalname);
form.append("file2", fs.createReadStream(file2.path,  file2.originalname);         

var headers = form.getHeaders();    
var config  = { headers:headers };     
axios.post(URL_SERVER2_UPLOAD_API, form, config)
 .then(function(response) { ... });

server2
上,我使用相同的 multer 中间件获取与
server1
中一样的文件。 在本地主机中一切正常,我可以在两台服务器之间传输文件。在 Heroku 上,我遇到了这些错误。这两个文件非常小(每个 150kb)。

====更新1

直接尝试

client --> server2
也失败了。这次我没有收到“超时”错误,但服务器只是在
req.files
中找不到文件,它是空的。 我不明白,因为它是完全相同的服务器配置,只是在另一个 heroku dyno 上。 与
multer-s3
相同:它在 localhost 上运行,而不是在 heroku 上运行。 这是服务器快速配置:

/** ======= server.js ======= */
var express     = require('express');
var app         = express();               
app.use(express.urlencoded({ extended: true })); // support encoded bodies

var server = app.listen(port, function() {...});

app.use('/my_route', require("my_route.js"));  
/** ======= my_route.js ======= */

var routes = express.Router(); 

function setupCORS(req, res, next) {
  res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Authorization,Content-type,Accept'); 
  
  if (req.method === 'OPTIONS') {
      res.status(200).end();
  } else {
      next();
  }
}

routes.all('/*', setupCORS);

/* ==============================
    UPLOAD MIDDLEWARE. 
============================== */
const multer  = require('multer');
let multer_storage = multer.diskStorage({..});
const form_upload = multer({..});

// API /my_route/upload
routes.post('/upload', form_upload.any(), function(req, res)
{
 // req.files it's empty here!
});
node.js express heroku multer form-data
2个回答
0
投票

我将首先回答一个不同的问题,这个问题已经有很多答案了,但我认为您的用例足够不同,足以保证一个问题。

上传的本地存储是一种反模式

在本地文件系统上存储上传内容是 Heroku1 上的反模式:它在大多数用例中无法按预期工作。 Dynos 有一个短暂的文件系统,这意味着对它们所做的任何更改都会在每次重新启动时丢失,这种情况经常发生且不可预测(每天至少一次)。

除非您只是在寻找临时存储空间,否则您将需要其他解决方案。 Heroku 建议 使用 Amazon S3 或 Azure Blob 存储之类的东西来存储上传内容。

我们通常谈论的两个好处是,上传可以在 dyno 重新启动后继续存在,并且水平缩放变得更加容易——您可以启动更多的 dyno,它们会自动看到上传的文件。您还可以处置测功机,而不必担心丢失数据。

跨服务共享文件

但在您的用例中,还有另一个好处:您的两个服务都可以访问同一个存储容器,这根本不需要复制文件。这是一个更干净的解决方案,如果您想将上传内容存储任意时间,则需要在 Heroku 上进行。


1我认为这在其他地方也是一种反模式,因为与 Heroku 相同原因


0
投票

最后,我解决了在

multer-s3
上使用
server1
,即能够接收req.files。然后我仅将链接传递给
server-2
,这将从 S3 下载文件。 即使这可能是一个更好的解决方案(正如 @Chris 所说),我也被迫使用
server1
作为第一个使用的服务,因为它是唯一正确接收文件的服务。我还是不知道为什么
service2
收到的总是空的
req.files

© www.soinside.com 2019 - 2024. All rights reserved.