最近做了个不一样的上传方式,其实上传文件是最常见的交互方式,前端上传的方式也很多。常见的有:
1. form + input 上传
<form action='uploadFile.php' enctype="multipart/form-data" type='post'> <input type='file'> <input type='hidden' name='userid'> <input type='hidden' name='signature'> <button>提交</button> </form>
优点:使用简单方便,兼容性好,基本所有浏览器都支持。
缺点:提交数据后页面不会跳转,前端无法知道什么时候上传结束,传输别的参数需要借助 type="hidden" 来完成
2. 使用 FromData 上传
使用js构造form表单的形式提交,简单高效,也是现在比较流行的做法
<input type="file" id="file" /> <script> let el = document.getElementById('file'); el.onchange = function(e) { const file = e.target.files[0]; const formData = new FormData(); formData.append("userid", userid); formData.append("signature", signature); formData.append("file", file); } </script>
缺点:不兼容IE10以下的浏览器
很遗憾。。我们的后端这两种均不支持。。需要采用文件流的形式上传
3. 采用ArrayBuffer 方式上传
let el = document.getElementById('file');
el.onchange = function(e) {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = async (e) => {
const buffer = reader.result; // 获取到一个文件的Arraybuffer
this.uploadBuffer(buffer); // 上传文件
};
reader.readAsArrayBuffer(file);
}
以上写法看起没什么问题。。也能正常上传。但是文件超过10M以上的数据,就会卡死。如果文件更大,浏览器就直接崩溃了
这时就需要将ArrayBuffer 进行切片上传
async uploadBuffer (buffer, startSzie = 0, index = 1) { let endSize = index * this.chunkSize; let res = buffer.slice(startSzie, endSize); try { // 上传视频片段 const { data } = await axios({ url: this.uploadUrl, method: 'post', data: res, headers: { 'Content-Type': '', 'Content-Range': `bytes ${startSzie}-${index * this.chunkSize}/${this.videoSzie}` } }); const { start, path, success } = data; if (success) { // 如果还有剩余,则递归上传,接口不支持并发 if (endSize <= this.videoSzie) { this.uploadBuffer(buffer, start, ++index); } else {this.uploadSuccess = true; const params = { userId: this.userId, author: this.userName, name: this.videoFileName, filePath: path, serverId: this.serverId, type: 1 }; // 全部片段上传成功之后,保存视频 const saveInfo = await IO.saveVideoInfo(params); if (saveInfo.list) { this.videoUrl.url = saveInfo.list; } } } } catch (error) { this.$toast('視頻上傳失敗'); this.closeVideo();this.uploadSuccess = true; } }
缺点:大文件上传会导致浏览器崩溃, 无法添加其他参数。上传相对较慢
兼容性还可以。基本能满足我们现在的业务场景
参考:
https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader/readAsArrayBuffer
https://www.w3cschool.cn/javascript_guide/javascript_guide-d2h126ad.html