【问题标题】:How to upload file using FormData with multer in node js, getting undefined in req.file and { } in req.body如何在节点js中使用带multer的FormData上传文件,在req.file中未定义,在req.body中获取{}
【发布时间】:2020-11-08 21:29:26
【问题描述】:

如何在 Node.js 中使用 FormData 和 multer 上传文件?我在 req.file 和 req.body 中得到 undefined 和 { }。

这是 HTML 代码:

<input type="file" name="file" id="file" onchange="angular.element(this).scope().uploadFile(this.files)">

这里是 JavaScript 代码:

$scope.uploadFile = function (files) {
        var fd = new FormData();
        //Take the first selected file
        console.log("files", files);
        fd.append("file", files[0]);
        $http({
            method: 'POST',
            url: 'http://localhost:5000/upload',
            headers: {
                'Content-Type': undefined
            },
            data: fd

        }).then(function (response) {
        }, function (error) {
        });

    };

这是服务器端代码:

var http = require('http');
var express = require('express');
var cors = require('cors');
var multer = require('multer');
var bodyParser = require('body-parser');
var upload = multer({ dest: 'public' });
var app = express();

app.use(cors());
app.use(bodyParser.json())

app.use(express.static('public'))

app.get('/', function (req, res) {
  res.sendStatus(200)
})


app.post('/upload', upload.single('file'), function (req, res) {

  console.log("req.file", req.file); //req.file undefined
  console.log("req.body", req.body); //req.body {}

});

app.listen(5000, function () {
  console.log("server listening on port 5000 ");

})

【问题讨论】:

    标签: javascript node.js file express


    【解决方案1】:

    后端代码看起来不错,但是您需要在客户端设置正确的内容类型。

    通过提供表单数据作为其数据参数,您实际上不必明确定义内容类型。所以你可以简单地做:

    $http('http://localhost:5000/upload', fd)
    

    如果要明确指定内容类型,可以使用:

    $http('http://localhost:5000/upload', fd, {
        headers: {
            'content-type': 'multipart/form-data'
        }
    })
    

    【讨论】:

    • 如果您使用邮递员之类的工具进行请求,上传是否有效?
    • 是的,它通过邮递员工作。但不是通过浏览器。
    【解决方案2】:

    尝试使用 ajax 来执行 POST 请求。

    var form = new FormData();
    form.append("file", files[0], "/path/to/file");
    
    var settings = {
      "url": "http://localhost:5000/upload",
      "method": "POST",
      "timeout": 0,
      "processData": false,
      "mimeType": "multipart/form-data",
      "contentType": false,
      "data": form
    };
    
    $.ajax(settings).done(function (response) {
      console.log(response);
    });
    

    【讨论】:

      【解决方案3】:

      我正在尝试使用 Koa 和 lowdb 建立一个简约的服务器;我还在 typescript 上编写所有内容,并使用实验功能来处理 (nodejs) koa 中的模块。

      我首先分享我的 .tsconfig

      {
        "compilerOptions": {
          "target": "es2017",
          "module": "ESNext",
          "lib": [
            "es6","DOM"
          ] ,
          "allowJs": true,
          "outDir": "build",
          "rootDir": "src" ,
          "strict": true ,
          "noImplicitAny": true,
          "moduleResolution": "node",                 
          "esModuleInterop": true,
         
          /* Advanced Options */
          "resolveJsonModule": true,
          "skipLibCheck": true,
          "forceConsistentCasingInFileNames": true
        }
      

      确实设法设置了服务器,但是当我想有效地添加 Multer 时遇到了很多麻烦,要从哪个库中选择来处理传入的数据。

      在这个POST 上有一个很好的讨论,最后我选择使用async-busboy [...] 似乎是最新的,当然,带来自己的类型.

      众所周知,koa 将一切都视为中间件,因此 async-await 上的包装器很有用!

      import multer from '@koa/multer';
      import koaStatic from 'koa-static';
      import path from 'path';
      import asyncBusboy from 'async-busboy';
      import multer from '@koa/multer';
      import koaStatic from 'koa-static';
      import path from 'path';
      import asyncBusboy from 'async-busboy';
      
      
      const router = new Router();
      const app = new Koa();
      
      const corsOpt = {
        origin: /* process.env.CORS_ALLOW_ORIGIN ||  */ '*', // this work well to configure origin url in the server
        methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'], // to works well with web app, OPTIONS is required
        allowedHeaders: ['Content-Type', 'Authorization'], // allow json and token in the headers
      };
      app.use(cors(corsOpt));
      app.use(logger());
      app.use(koaBody());
      
      app.use(koaStatic(__dirname + './static/uploads'));
      
      const storage = multer.diskStorage({
        destination: function (req, file, cb) {
          cb(null, './uploads');
        },
        filename: function (req, file, cb) {
          const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
          cb(null, file.fieldname + '-' + uniqueSuffix + '.jpg');
        },
      });
      const upload = multer({ storage });
      
      app.use(upload.any());
      
      app.use(async function (ctx: KoaContext, next: () => any) {
        // ignore non-POSTs
        if ('POST' != ctx.method) return await next();
        const { files, fields } = await asyncBusboy(ctx.req);
        console.log(files);
        let err = await upload
          .single('file')(ctx as any, next)
          .then((res: any) => res)
          .catch((err: any) => err);
        if (err) {
          ctx.body = {
            code: 0,
            msg: err.message,
          };
        } else {
          ctx.body = {
            code: 1,
            data: files,
          };
        }
      });
      
      // add a route for uploading multiple files
      router.post('/uploader', upload.fields([]), (ctx: KoaContext) => {
        console.log('ctx.request.files', ctx.request.files);
        console.log('ctx.files', ctx);
        console.log('ctx.request.body', ctx.request.body);
        ctx.body = 'done';
      });
      
      // REST OF CODE ...
      
      app.use(router.routes()).use(router.allowedMethods());
      
      app.listen(4040);
      console.log('server running ... http://localhost:4040');
      
      

      我仍在学习,或者说通过做这样的实验来破解所有打字稿的秘密。现在我确实有冲突,因为 mutler 正在做自己的表单数据(我假设通过从其他帖子中读取)到目前为止,这是通过 async-await 从 ctx.req.file 获取文件的解决方案,但我仍然在努力与类型。

      你可以在这里查看整个项目repo

      任何关于类型的帮助都会很棒。

      希望现在使用 typescript 有助于进一步讨论。

      【讨论】:

      • 这并不能真正回答问题。如果您有其他问题,可以点击 进行提问。要在此问题有新答案时收到通知,您可以follow this question。一旦你有足够的reputation,你也可以add a bounty 引起更多的关注。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-12-03
      • 2018-08-04
      • 2016-06-25
      • 1970-01-01
      • 2019-02-06
      • 2021-08-21
      • 2020-10-02
      相关资源
      最近更新 更多