如何在nodejs中使用带有multer的FormData上传文件,在req.file中未定义,在req.body中{}



如何在Node.js中使用带有multer的FormData上传文件?我在req.file中得到了未定义,在req.body.中得到了{}

这是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 ");
})

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

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

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

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

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

尝试使用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);
});

我正在尝试使用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将一切都视为中间件,因此异步等待上的包装器非常有用!

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 wait从ctx.req.file获取文件是一个解决方案,但我仍然在处理类型。

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

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

希望这有助于进一步讨论现在打字。

最新更新