Nodejs express formidable(不使用body-parser) 多文件上传 请教
Nodejs express formidable(不使用body-parser) 多文件上传 请教
由于新版本的express 使用:app.use(express.json());app.use(express.urlencoded());app.use(require(‘connect-multiparty’)()); //(connect-multiparty需要另外安装) 来代替app.use(express.bodyParser()); 那么我想着如何在不使用app.use(express.bodyParser({ keepExtensions: true, uploadDir: ‘./public/images’ }));的情况下,使用formidable来实现多文件上传呢?
问题来了看代码(代码是照着那个博客代码写的): app.js app.use(express.json()); app.use(express.urlencoded()); //app.use(express.multipart()); app.use(require(‘connect-multiparty’)()); //app.js中其他代码未列出 和 博客实例app.js代码是相同的。
upload.ejs:
<%- include header %>
<form method='post' action='/upload' enctype='multipart/form-data' >
<input type="file" name='file1'/><br>
<input type="file" name='file2'/><br>
<input type="file" name='file3'/><br>
<input type="file" name='file4'/><br>
<input type="file" name='file5'/><br>
<input type="submit" />
</form>
<%- include footer %>
index.js: 路由处理部分
var crypto = require('crypto'), //可用其生成散列值来加密
fs = require('fs'),
User = require('../models/user.js');
var Post = require('../models/post.js');
var formidable = require('formidable');
app.post(’/upload’, function(req, res){
var form = new formidable.IncomingForm();
form.uploadDir = './public/images/'; //上传目录
form.keepExtensions = true; //保留后缀格式
form.maxFieldsSize = 2*1024*1024; //文件大小
console.log('new formidable',form);
return res.redirect('/'); //这是为了测试
form.parse(req, function(err, fields, files){
/*if (err){
req.flash('error', '文件上传失败');
return res.redirect('/upload');
}*/
//console.log('formidable fields:', fields);
/* for (var i in files){
if (files[i].size == 0){
//使用同步方式删除一个文件
fs.unlinkSync(files[i].path);
console.log('file path:',files[i].path);
console.log('success remove a empty file');
}else{
var target_path = './public/images/' + files[i].name; //这里重名时 一定要注意
//使用同步方式重命名一个文件
fs.renameSync(files[i].path, target_path);
console.log('successfully rename a file');
}
}*/
// req.flash('success', '文件上传成功!');
//res.redirect('/upload');
});
问题:如果没有在 form.parse()前使用return 那么点击上传时, 页面会一直显示正在加载,估计是异步哪里的问题。 接下来我用app.post(’/upload’, function(req, res){ console.log(‘new formidable’,form); return res.redirect(’/’); } 这个测试 ,文件可以上传,并且打印出的信息:
new formidable { domain: null,
_events: {},
_maxListeners: 10, error: null, ended: false, maxFields: 1000, maxFieldsSize: 2097152, keepExtensions: false, uploadDir: ‘C:\Users\ADMINI~1\AppData\Local\Temp’, //看这里 encoding: ‘utf-8’, headers: null, type: null, hash: false, multiples: false, bytesReceived: null, bytesExpected: null, _parser: null, _flushing: 0, _fieldsSize: 0, openedFiles: [] }
通过以上信息我们可以看到 文件上传到’C:\Users\ADMINI~1\AppData\Local\Temp ,然后我查找这个路径,发现文件确实上传到这里了。 然后我有在app.post(’/upload’, function(req, res){
var form = new formidable.IncomingForm();
form.uploadDir = './public/images/'; //上传目录
form.keepExtensions = true; //保留后缀格式
form.maxFieldsSize = 2*1024*1024; //文件大小
console.log('new formidable',form);
return res.redirect('/'); //这是为了测试}
测试后发现打印出来的 uploadDir: ‘./public/images/’, 说明上传路径改变了 但是文件还是保存在’C:\Users\ADMINI~1\AppData\Local\Temp。
是我的思路错了么? 还是不使用bodyParser()就不能使用forimidable . 到底该如何将文件上传到指定的目录呢?并且要删掉那些上传的空文件??求各位大大赐教 不胜感激!! 要上班走了 ,写的匆忙 见谅!!
要在不使用 body-parser
的情况下使用 formidable
实现多文件上传,你需要确保 formidable
正确地解析请求并处理文件上传。以下是一个完整的示例,展示如何配置和使用 formidable
来处理文件上传。
安装必要的依赖
首先,确保你已经安装了 express
和 formidable
:
npm install express formidable
项目结构
假设你的项目结构如下:
project-root/
├── app.js
├── index.js
├── views/
│ └── upload.ejs
└── public/
└── images/
app.js
const express = require('express');
const formidable = require('formidable');
const path = require('path');
const app = express();
const port = 3000;
// 设置静态文件目录
app.use(express.static(path.join(__dirname, 'public')));
// 设置模板引擎
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// 路由
app.get('/', (req, res) => {
res.render('upload');
});
app.post('/upload', (req, res) => {
const form = new formidable.IncomingForm();
// 配置 formidable
form.uploadDir = path.join(__dirname, 'public/images');
form.keepExtensions = true;
form.maxFieldsSize = 2 * 1024 * 1024; // 2MB
form.parse(req, (err, fields, files) => {
if (err) {
console.error('Error parsing form:', err);
return res.status(500).send('File upload failed.');
}
// 检查是否有空文件
Object.values(files).forEach(file => {
if (file.size === 0) {
// 删除空文件
fs.unlinkSync(file.path);
console.log(`Empty file removed: ${file.path}`);
}
});
res.send('Files uploaded successfully!');
});
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}/`);
});
upload.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Upload Files</title>
</head>
<body>
<h1>Upload Multiple Files</h1>
<form method="POST" action="/upload" enctype="multipart/form-data">
<input type="file" name="file1" multiple /><br>
<input type="file" name="file2" multiple /><br>
<input type="file" name="file3" multiple /><br>
<input type="submit" value="Upload" />
</form>
</body>
</html>
解释
-
配置
formidable
:form.uploadDir
指定文件上传的目标目录。form.keepExtensions
保留文件的扩展名。form.maxFieldsSize
限制单个字段的最大大小。
-
处理文件上传:
- 在
form.parse
回调函数中,你可以访问上传的文件列表 (files
)。 - 检查每个文件的大小,如果为零则删除该文件。
- 在
-
模板:
- 使用 EJS 模板引擎渲染上传表单。
- 表单的
enctype
属性设置为multipart/form-data
,以支持文件上传。
通过这种方式,你可以使用 formidable
在 Express 中处理多文件上传,并将文件保存到指定的目录。
如果有什么思路,也请赐教
uploadDir目录要加上绝对路径,_dirname
我不知道你是什么问题,不过我贴我上传文件的模块给你吧,事实上,上传多个文件有专门的module,我用的是busboy
router.post('/upload',function(req,res){
req.pipe(req.busboy)
//要上传的文件数目
var fileNum = 3;
var fileCount = 0;
var filepath = path.join(path.normalize(__dirname + '/..'),'public','images')
req.busboy.on('file',function(fieldname,file,filename){
// console.log('++upload ' + filepath+'/'+filename)
var fstream
if(filename !== ""){
fstream = fs.createWriteStream(filepath+'/'+filename.trim());
file.pipe(fstream);
}
fstream.on('close', function () {
if(++fileCount == fileNum)
res.redirect('/');
});
})
要使用 formidable
实现多文件上传而不使用 body-parser
或者 connect-multiparty
,你需要确保 formidable
正确配置并处理请求。以下是完整的示例代码及说明:
示例代码
app.js
const express = require('express');
const app = express();
const port = 3000;
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get('/', (req, res) => {
res.sendFile(__dirname + '/upload.ejs');
});
app.post('/upload', (req, res) => {
const form = new formidable.IncomingForm();
form.uploadDir = './public/images/'; // 设置上传目录
form.keepExtensions = true; // 保留文件扩展名
form.maxFieldsSize = 2 * 1024 * 1024; // 最大字段大小为2MB
form.parse(req, (err, fields, files) => {
if (err) {
console.error('Upload error:', err);
res.status(500).send('File upload failed');
return;
}
// 遍历所有上传的文件
Object.values(files).forEach(file => {
if (file.size === 0) {
// 删除空文件
fs.unlinkSync(file.path);
} else {
// 移动文件到目标位置
fs.renameSync(file.path, './public/images/' + file.name);
}
});
res.send('Files uploaded successfully');
});
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
说明
- 引入模块:首先需要引入
express
和formidable
模块。 - 设置中间件:使用
express.json()
和express.urlencoded()
中间件处理 JSON 和 URL 编码的数据。 - 处理 GET 请求:提供一个简单的 GET 请求处理程序,用于渲染上传表单。
- 处理 POST 请求:在 POST 请求处理程序中创建一个新的
formidable.IncomingForm
对象,并进行配置:uploadDir
:设置上传文件的目录。keepExtensions
:保留文件的扩展名。maxFieldsSize
:设置最大字段大小。
- 解析请求:调用
form.parse(req, callback)
解析请求数据,并在回调函数中处理上传的文件:- 如果发生错误,返回错误信息。
- 遍历所有上传的文件,如果文件大小为零,则删除文件;否则,移动文件到目标目录。
这样就可以正确地将文件上传到指定目录,并删除空文件。希望这能解决你的问题。