先简单写个html如下
<input id="fileInput" type="file" name="" />
<span id="progress">0%</span>
<a id="upload" href="javascript:;">上传</a>
点击上传时,添加参数,提交到后台,并显示进度条
upload.addEventListener('click', function () {
var file = fileInput.files[0];
if (!file) {
alert('请选择上传文件');
return
}
var params = new FormData();
params.append('file', file);
params.append('otherParams', 'xxx'); // 其他必要参数
var xhr = new XMLHttpRequest();
xhr.onerror = function () {
alert('请求失败');
}
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
console.log(xhr.responseText);
} else {
console.error(xhr.status)
}
}
}
xhr.upload.onprogress = function (e) {
progress.innerHTML = Math.round(e.loaded / e.total * 100) + '%';
}
xhr.open('POST', 'http://localhost:8901/api/upload', true);
xhr.send(params);
});
为了实现上传,用nodejs写一个简单的本地服务,代码如下
const http = require('http');
const fs = require('fs');
http.createServer((req, res) => {
if (req.url === '/api/upload') {
res.writeHead(200, {
'Content-Type': 'application/json;charset=UTF-8',
"Access-Control-Allow-Origin": "*" // 允许跨域上传
});
// multipart/form-data; boundary=----WebKitFormBoundaryWDxUdTi37Gtg5R5y
var splitStr = req.headers['content-type'].split('; boundary=')[1];
var data = '';
req.on('data', chunk => {
data += chunk;
});
req.on('end', () => {
var json = normalizeFormData(data, splitStr);
res.end(JSON.stringify(json));
})
} else {
fs.readFile('upload-demo.html', 'utf8', (err, data) => {
if (err) {
res.writeHead(200, {'Content-Type': 'application/json;charset=UTF-8'});
res.end(JSON.stringify(err));
} else {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(data);
}
});
}
}).listen(8901);
function normalizeFormData(chunk, splitStr) {
var arr = chunk.toString().split(splitStr);
arr = arr.slice(1, arr.length - 1);
var json = {};
var reName = /Content-Disposition: form-data; name="(w+)"/;
for (var i = 0; i < arr.length; i++) {
let arr2 = arr[i].split('n');
let name = arr2[1].match(reName)[1];
if (name === 'file') {
let reFileName = /filename="([w-.u4e00-u9fa5]+)"/;
let filename = arr2[1].match(reFileName)[1];
json[name] = filename;
} else {
// 去掉尾部r
json[name] = arr2[3].substr(0, arr2[3].length - 1);
}
}
return json
}
黑窗口运行上个文件
node server.js
,打开http://localhost:8901/
效果图如下:
https://www.zhihu.com/video/1071719205090598912
大文件上传 -> 文件上传带进度条进阶-断点续传
附: 在线地址
- 单文件上传
- 多文件上传