nodejs文件无刷新上传
文件上传是网站最基本的操作之一。这两天研究了NodeJs环境下的文件上传问题,使用到了ExpressJS-4.12.1框架和multiparty工具包。整个上传采用RFC1867协议,即基于HTML表单的文件上传协议。借助这个协议,为表单增加enctype="multipart/form-data"属性,再使用type为file的input控制来选择文件,然后便可用POST方法上传文件。
传统的表单上传,属于"同步上传"。也就是说,点击上传按钮后,网页"锁死",用户只能等待上传结束,然后浏览器刷新,跳到表单的action属性指定的网址。显然,“同步上传”用户体验差。本文采用iframe和ajax两种方式,实现文件无刷新“异步”上传。
iframe方式
iframe虽然有很多缺点,但是利用它解决文件无刷新上传却是一个非常nice的方案。好处显而易见,因为几乎所有浏览器都支持iframe,所以兼容性非常棒。
原理:将form表单的target属性指向一个页面中隐藏的iframe,这使得上传结束后,服务器将结果返回iframe窗口,所以当前页面就不会跳转了。其次,同域iframe可以调用当前页面的js函数,这样就能将服务器返回的信息,从iframe窗口传到上层页面。
关键代码如下:
上传页面:node-iframe.hbs
<!-- 用于上传的form表单 -->
<form method="post" enctype="multipart/form-data" action="/file-upload/iframe" target="hidden_frame">
<div>用户:<input type="text" name="username"></div>
<div>密码:<input type="password" name="password"></div>
<div><input type="file" name="upload1" multiple="multiple"></div>
<div><input type="file" name="upload2" multiple="multiple"></div>
<input type="submit">
</form>
<!-- 隐藏的iframe -->
<iframe src="hidden_frame" id="hidden_frame" name="hidden_frame" style="display: none;"></iframe>
<div id="msg"></div>
<script>
/* 结果回调函数 */
function callback(result) {
document.getElementById("msg").innerHTML = "<span>"+result+"</span>";
}
</script>
路由配置:index.js
/* GET node-iframe page. */
router.get('/node-iframe', function(req, res, next) {
res.render('node-iframe', { title: 'node-iframe' });
});
/* handle file upload */
router.post('/file-upload', function(req, res, next) {
var form = new multiparty.Form({ uploadDir: './uploadDir/'});
form.parse(req, function(err, fields, files) {
console.log(files); // 文件信息
console.log(fields); // 普通信息
if (err) {
console.log('parser error : ' + err);
} else {
// 考虑多文件上传
for (var p in files) {
var file = files[p];
if (file[0].size == 0) continue;
var uploadedPath = file[0].path;
var dstPath = './uploadDir/' + file[0].originalFilename;
fs.rename(uploadedPath, dstPath, function(err) {
if (err) {
console.log('rename error : ' + err);
} else {
console.log('rename ok!');
}
});
}
}
// 注意返回的content-type为text/html
res.writeHead(200, {'content-type': 'text/html'});
// 利用parent.callback()调用父级函数
res.write("<script>parent.callback('success!!!');</script>");
res.end();
});
return;
});
ajax方式
HTML5提出了XMLHttpRequest对象的第二版,从此ajax能够上传文件了,这是真正的“异步上传”,主要是利用了FormData对象。需要注意的是,并非所有浏览器都完整地实现了XMLHttpRequest2级规范。
关键代码如下:
上传页面:node-ajax.hbs
<!-- 上传表单 -->
<form method="post" enctype="multipart/form-data" id="uploadform">
<div>用户:<input type="text" name="username"></div>
<div>密码:<input type="password" name="password"></div>
<div><input type="file" name="upload1" multiple="multiple"></div>
<div><input type="file" name="upload2" multiple="multiple"></div>
<input type="button" id="upload" value="上传">
</form>
<p id="msg"></p>
<script src="/javascripts/jquery-2.1.1.min.js"></script>
<script>
$('#upload').click(function() {
// 创建formdata对象
var formData = new FormData($('#uploadform')[0]);
$.ajax({
url: '/file-upload',
type: 'post',
data: formData,
cache: false,
contentType: false,
processData: false,
success: function(data) {
$('#msg').text('success!!');
},
error: function() {
$('#msg').text('error!!');
}
});
});
</script>
路由配置:index.js
/* GET node-ajax page. */
router.get('/node-ajax', function(req, res, next) {
res.render('node-ajax', { title: 'node-ajax' });
});
/* handle file upload */
router.post('/file-upload', function(req, res, next) {
var form = new multiparty.Form({ uploadDir: './uploadDir/'});
form.parse(req, function(err, fields, files) {
console.log(files); // 文件信息
console.log(fields); // 普通信息
if (err) {
console.log('parser error : ' + err);
} else {
// 考虑多文件上传
for (var p in files) {
var file = files[p];
if (file[0].size == 0) continue;
var uploadedPath = file[0].path;
var dstPath = './uploadDir/' + file[0].originalFilename;
fs.rename(uploadedPath, dstPath, function(err) {
if (err) {
console.log('rename error : ' + err);
} else {
console.log('rename ok!');
}
});
}
}
// 返回
res.writeHead(200, {'content-type': 'text/plain'});
res.end();
});
return;
});
代码合并
由于,两种上传方式的后台代码几乎一样,唯一区别在于返回的响应不一样。可通过路由规则(/file-upload/:way),将两段代码合并。
/* handle file upload */
router.post('/file-upload/:way', function(req, res, next) {
var form = new multiparty.Form({ uploadDir: './uploadDir/'});
form.parse(req, function(err, fields, files) {
console.log(files); // 文件信息
console.log(fields); // 普通信息
if (err) {
console.log('parser error : ' + err);
} else {
// 考虑多文件上传
for (var p in files) {
var file = files[p];
if (file[0].size == 0) continue;
var uploadedPath = file[0].path;
var dstPath = './uploadDir/' + file[0].originalFilename;
fs.rename(uploadedPath, dstPath, function(err) {
if (err) {
console.log('rename error : ' + err);
} else {
console.log('rename ok!');
}
});
}
}
// 不同的请求方式,不同的返回
var way = req.params.way;
if (way === 'iframe') {
res.writeHead(200, {'content-type': 'text/html'});
res.write("<script>parent.callback('success!!!');</script>");
} else if (way === 'ajax') {
res.writeHead(200, {'content-type': 'text/plain'});
}
res.end();
});
return;
});
别忘了,修改action="/file-upload/iframe"和url: '/file-upload/ajax'。
结语
利用node实现文件上传还是挺简单的,完整代码请戳这!
参考
建议继续学习:
- 为什么我们要从 NodeJS 迁移到 Ruby on Rails (阅读:5936)
- JavaScript,只有你想不到 (阅读:5799)
- Nodejs和MongoDB初体验 (阅读:5506)
- Codeigniter里的无刷新上传 (阅读:5153)
- 使用socket.io和node.js搭建websocket应用 (阅读:4874)
- nodejs教程:配置nodejs.exe的windows目录结构 (阅读:4239)
- node.js调研与服务性能测试 (阅读:4175)
- 基于express+socket.io的nodejs聊天室 (阅读:4070)
- 渐进增强的无刷新多图片上传控件(iFrame+HTML5) (阅读:4116)
- nodejs教程:安装及配置app.js文件 (阅读:3115)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:chenjun 来源: 风影博客
- 标签: nodejs 刷新
- 发布时间:2016-02-20 16:47:13
-
[914] WordPress插件开发 -- 在插件使用 -
[135] 解决 nginx 反向代理网页首尾出现神秘字 -
[54] 整理了一份招PHP高级工程师的面试题 -
[53] 如何保证一个程序在单台服务器上只有唯一实例( -
[52] 海量小文件存储 -
[52] 全站换域名时利用nginx和javascri -
[52] Innodb分表太多或者表分区太多,会导致内 -
[51] 用 Jquery 模拟 select -
[50] CloudSMS:免费匿名的云短信 -
[48] 分享一个JQUERY颜色选择插件
