最近做了個不一樣的上傳方式,其實上傳文件是最常見的交互方式,前端上傳的方式也很多。常見的有:
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