然后在后续中间件内得到已保存的文件的信息,再做二次处理。
- ctx.request.files.f1 得到文件信息,f1为input file 标签的 name
- 获得文件的扩展名,重命名文件
NODE
/**
* 服务入口
*/
var http = require('http');
var koaStatic = require('koa-static');
var path = require('path');
var koaBody = require('koa-body');//文件保存库
var fs = require('fs');
var Koa = require('koa2');
var app = new Koa();
var port = process.env.PORT || '8100';
var uploadHost= `http://localhost:${port}/uploads/`;
app.use(koaBody({
formidable: {
//设置文件的默认保存目录,不设置则保存在系统临时目录下 os
uploadDir: path.resolve(__dirname, '../static/uploads')
},
multipart: true // 开启文件上传,默认是关闭
}));
//开启静态文件访问
app.use(koaStatic(
path.resolve(__dirname, '../static')
));
//文件二次处理,修改名称
app.use((ctx) => {
var file = ctx.request.files.f1;//得道文件对象
var path = file.path;
var fname = file.name;//原文件名称
var nextPath = path fname;
if(file.size>0 && path){
//得到扩展名
var extArr = fname.split('.');
var ext = extArr[extArr.length-1];
var nextPath = path '.' ext;
//重命名文件
fs.renameSync(path, nextPath);
}
//以 JSON 形式输出上传文件地址
ctx.body = `{
"fileUrl":"${uploadHost}${nextPath.slice(nextPath.lastIndexOf('/') 1)}"
}`;
});
/**
* http server
*/
var server = http.createServer(app.callback());
server.listen(port);
console.log('demo1 server start ...... ');
复制代码
CODE
https://github.com/Bigerfe/fe-learn-code/tree/master/src/upfiles-demo
多文件上传在 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
局部刷新 - 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
无刷新上传无刷新上传文件肯定要用到XMLHttpRequest,在 ie 时代也有这个对象,单只 支持文本数据的传输,无法用来读取和上传二进制数据。
现在已然升级到了XMLHttpRequest2,较1版本有非常大的升级,首先就是可以读取和上传二进制数据,可以使用·FormData·对象管理表单数据。
当然也可使用 fetch 进行上传。
DEMO
HTML
<div>
选择文件(可多选):
<input type="file" id="f1" multiple/><br/><br/>
<button type="button" id="btn-submit">上 传</button>
</div>
复制代码
JS xhr
<script>
function submitUpload() {
//获得文件列表,注意这里不是数组,而是对象
var fileList = document.getElementById('f1').files;
if(!fileList.length){
alert('请选择文件');
return;
}
var fd = new FormData(); //构造FormData对象
fd.append('title', document.getElementById('title').value);
//多文件上传需要遍历添加到 fromdata 对象
for(var i =0;i<fileList.length;i ){
fd.append('f1', fileList[i]);//支持多文件上传
}
var xhr = new XMLHttpRequest(); //创建对象
xhr.open('POST', 'http://localhost:8100/', true);
xhr.send(fd);//发送时 Content-Type默认就是: multipart/form-data;
xhr.onreadystatechange = function () {
console.log('state change', xhr.readyState);
if (this.readyState == 4 && this.status == 200) {
var obj = JSON.parse(xhr.responseText); //返回值
console.log(obj);
if(obj.fileUrl.length){
alert('上传成功');
}
}
}
}
//绑定提交事件
document.getElementById('btn-submit').addEventListener('click',submitUpload);
</script>
复制代码
JS Fetch
fetch('http://localhost:8100/', {
method: 'POST',
body: fd
})
.then(response => response.json())
.then(response =>{
console.log(response);
if (response.fileUrl.length) {
alert('上传成功');
}
} )
.catch(error => console.error('Error:', error));
复制代码
CODE
https://github.com/Bigerfe/fe-learn-code/tree/master/src/upfiles-demo
多文件,单进度借助XMLHttpRequest2的能力,实现多个文件或者一个文件的上传进度条的显示。
DEMO