这是《大胖小课》栏目的专题一《说说文件上传那些事儿》的第3节-《不用 js 实现文件无刷新上传》
专题已经更新章节:
《大胖 • 小课》- 我是这样理解文件上传的
《大胖 • 小课》- 写一个 node 的文件上传接口
上一节,我们实现了一个简单的文件上传接口,服务端的文件保存我们使用
koa-body
来完成。
从这节开始我们开始进行梳理前端各种文件上传的场景。
既然要说不用
js
实现文件无刷新上传,那就要先说说最原始的文件上传,也就是在
ie
时代是怎么处理的。
最原始的文件上传
使用 form 表单上传文件在
ie
时代,如果实现一个无刷新的文件上传那可是费老劲了,大部分都是用 iframe 来实现局部刷新或者使用 flash 插件来搞定,在那个时代
ie
就是最好用的浏览器(别无选择)。
DEMO

这种方式上传文件,不需要 js ,而且没有兼容问题,所有浏览器都支持,就是体验很差,导致页面刷新,页面其他数据丢失。
HTML
<form method="post" action="http://localhost:8100" enctype="multipart/form-data">
选择文件:
<input type="file" name="f1"/> input 必须设置 name 属性,否则数据无法发送<br/>
<br/>
标题:<input type="text" name="title"/><br/><br/><br/>
<button type="submit" id="btn-0">上 传</button>
</form>
多文件上传
在
ie
时代的多文件上传是需要创建多个
input file
标签,现在
html5
只需要一个标签加个属性就搞定了,
file
标签开启
multiple
。
DEMO
HTML
//设置 multiple属性
<input type="file" name="f1" multiple/>
NODE
文件上传接口也需要进行简单的调整,由单文件对象的获取变为多文件数组,然后进行遍历处理。
//中间件处理文件重命名
app.use((ctx) => {
var files = ctx.request.files.f1;// 多文件, 得到上传文件的数组
var result=[];
//遍历处理
files && files.forEach(item=>{
var path = item.path;
var fname = item.name;//原文件名称
var nextPath = path + fname;
if (item.size > 0 && path) {
//得到扩展名
var extArr = fname.split('.');
var ext = extArr[extArr.length - 1];
var nextPath = path + '.' + ext;
//重命名文件
fs.renameSync(path, nextPath);
//文件可访问路径放入数组
result.push(uploadHost+ nextPath.slice(nextPath.lastIndexOf('/') + 1));
}
});
//输出 json 结果
ctx.body = `{
"fileUrl":${JSON.stringify(result)}
}`;
})
CODE
https://github.com/Bigerfe/fe-learn-code/tree/master/src/upfiles-demo/demo2
局部刷新(不用 js 的无刷新上传) - iframe
这里说的是在
ie
时代的上传文件局部刷新,借助 iframe 实现。
DEMO
- 局部刷新
页面内放一个隐藏的
iframe
,或者使用
js
动态创建,指定
form
表单的
target
属性值为
iframe
标签 的
name
属性值,这样
form
表单的
shubmit
行为的跳转就会在
iframe
内完成,整体页面不会刷新。
- 拿到接口数据
然后为
iframe
添加
load
事件,得到
iframe
的页面内容,将结果转换为
JSON
对象,这样就拿到了接口的数据
HTML
<iframe id="temp-iframe" name="temp-iframe" src="" style="display:none;"></iframe>
<form method="post" target="temp-iframe" action="http://localhost:8100" enctype="multipart/form-data">
选择文件(可多选):
<input type="file" name="f1" id="f1" multiple/><br/> input 必须设置 name 属性,否则数据无法发送<br/>
<br/>
标题:<input type="text" name="title"/><br/><br/><br/>
<button type="submit" id="btn-0">上 传</button>
</form>
<script>
var iframe = document.getElementById('temp-iframe');
iframe.addEventListener('load',function () {
var result = iframe.contentWindow.document.body.innerText;
//接口数据转换为 JSON 对象
var obj = JSON.parse(result);
if(obj && obj.fileUrl.length){
alert('上传成功');
}
console.log(obj);
});
</script>
NODE
服务端代码不需要改动,略.
CODE
https://github.com/Bigerfe/fe-learn-code/tree/master/src/upfiles-demo/demo3
小结
本节主要是介绍了下在 ie 时代通常是怎样实现文件上传和无刷新上传的,虽然现在的大前端时代已经支持体验更好的方式实现,但是本质的原理都不会变,只是工具(浏览器)升级了。
作者 zz_jesse, 专注前端领域,深更原理和实现,目前在公司主要负责技术架构和团队管理。
个人开源项目 :react ssr 开发骨架 Zz.js, https://github.com/Bigerfe/koa-react-ssr
个人公众号:@《前端张大胖》 欢迎关注,深度好文以及各种福利在等你。