前言
近期有一個項目需求是做一個 公司內部的 知識庫 模塊。要求實現文件、文件夾上傳,以及后續的文檔在線預覽、下載、刪除、新建空文件夾等類似於一個網盤的業務。搜索一圈,發現了這個插件,而且插件的參數事件信息也挺齊全,缺點就是貌似作者沒有維護了,后續出現了bug只能自行解決。用於一個基本的文件、文件夾上傳需求還是可以滿足,使用的話還請自行思量。
簡介
vue-simple-uploader 是基於 simple-uploader.js 和Vue結合做的一個上傳組件,自帶 UI,可覆蓋、自定義。它支持文件、多文件、文件夾上傳;支持拖拽文件、文件夾上傳;可暫停、繼續上傳;支持秒傳;上傳隊列管理,支持最大並發上傳;分片上傳;支持進度、預估剩余時間、出錯自動重試、重傳等操作。
查看演示:https://www.helloweba.net/demo/2020/vueuploader/#/
配置
安裝:
npm install vue-simple-uploader --save
初始化,在main.js中添加如下代碼:
import Vue from 'vue'
import uploader from 'vue-simple-uploader'
import App from './App.vue'
Vue.use(uploader)
使用
<template> <uploader :options="options" class="uploader-example"> <uploader-unsupport></uploader-unsupport> <uploader-drop> <p>Drop files here to upload or</p> <uploader-btn>select files</uploader-btn> <uploader-btn :attrs="attrs">select images</uploader-btn> <uploader-btn :directory="true">select folder</uploader-btn> </uploader-drop> <uploader-list></uploader-list> </uploader> </template> <script> export default { data () { return { options: { target: 'http://localhost:9000/upload', testChunks: false, chunkSize: 1024*1024*2, //1MB simultaneousUploads: 3, //並發上傳數 headers: { 'access-token': 'abcd1234' }, query :{ code : 123 } }, attrs: { accept: 'image/*' } } } } </script> <style> .uploader-example { width: 880px; padding: 15px; margin: 40px auto 0; font-size: 12px; box-shadow: 0 0 10px rgba(0, 0, 0, .4); } .uploader-example .uploader-btn { margin-right: 4px; } .uploader-example .uploader-list { max-height: 440px; overflow: auto; overflow-x: hidden; overflow-y: auto; } </style>
傳遞參數
插件使用時,上傳請求都會包含如下分塊信息:
chunkNumber
: 當前塊的次序,第一個塊是 1,注意不是從 0 開始的。totalChunks
: 文件被分成塊的總數。chunkSize
: 分塊大小,根據totalSize
和這個值你就可以計算出總共的塊數。注意最后一塊的大小可能會比這個要大。currentChunkSize
: 當前塊的大小,實際大小。totalSize
: 文件總大小。identifier
: 這個就是每個文件的唯一標示。filename
: 文件名。relativePath
: 文件夾上傳的時候文件的相對路徑屬性。
后端可根據傳遞的信息自由處理;一般是一個文件表一個文件夾表做關聯。
狀態碼
200
,201
,202
: 當前塊上傳成功,不需要重傳。404
,415
.500
,501
: 當前塊上傳失敗,會取消整個文件上傳。- 其他狀態碼: 出錯了,但是會自動重試上傳。
配置項
由於是對原simple-upload.js做的封裝,大多數的配置可以參考原生js文檔,部分配置與原生有些許不同,請注意仔細查看相關參考文檔。
target
:目標上傳地址URL,默認值為 '/'。
chunkSize
:分片時按照該值來分。最后一個上傳分片的大小是可能是大於等於1倍的這個值但是小於兩倍的這個值大小
simultaneousUploads
:並發上傳數,默認 3。
fileParameterName
:上傳文件時文件的參數名,默認 file。
headers
:額外的一些請求頭,例如有時我們需要在header中向后台傳遞token,默認為對象: {}。
maxChunkRetries
:最大自動失敗重試上傳次數,值可以是任意正整數,如果是 undefined 則代表無限次,默認 0。
chunkRetryInterval
:重試間隔,值可以是任意正整數,如果是 null 則代表立即重試,默認 null。
parseTimeRemaining(timeRemaining, parsedTimeRemaining) {Function}
:格式化剩余時間。以下代碼把英文時間轉成中文:
parseTimeRemaining: function (timeRemaining, parsedTimeRemaining) {
return parsedTimeRemaining
.replace(/\syears?/, '年')
.replace(/\days?/, '天')
.replace(/\shours?/, '小時')
.replace(/\sminutes?/, '分鍾')
.replace(/\sseconds?/, '秒')
}
屬性
autoStart {Boolean}
:默認 true, 是否選擇文件后自動開始上傳。
fileStatusText {Object}
:文件狀態,文件在上傳時會響應幾種狀態:
{
success: 'success',
error: 'error',
uploading: 'uploading',
paused: 'paused',
waiting: 'waiting',
}
事件
fileAdded(file)
:添加了一個文件事件,一般用做文件校驗,比如要校驗文件md5時,先觸發該事件。 可以當作上傳前的鈎子,校驗文件類型、大小或者數量限制等
fileSuccess(rootFile, file, message, chunk)
:一個文件上傳成功事件,第一個參數 rootFile 就是成功上傳的文件所屬的根 Uploader.File 對象,它應該包含或者等於成功上傳文件;第二個參數 file 就是當前成功的 Uploader.File 對象本身;第三個參數就是 message 就是服務端響應內容,永遠都是字符串;第四個參數 chunk 就是 Uploader.Chunk 實例,它就是該文件的最后一個塊實例,如果你想得到請求響應碼的話,chunk.xhr.status 就是。
fileError(rootFile, file, message, chunk)
:上傳出錯。
fileProgress(rootFile, file, chunk)
:一個文件在上傳中,監聽文件上傳進度。
fileRemoved(rootFile, file)
:從上傳列表移除文件。
注意:所有的事件都會通過 lodash.kebabCase 做轉換,例如 fileSuccess
就會變成 file-success
。
方法綁定的使用:
<uploader ref="uploader" class="avatar-uploader":options="options" :file-status-text="statusText" @file-added="onFileAdded" @file-success="onFileSuccess" @file-progress="onFileProgress" @file-error="onFileError" @file-removed="fileRemoved">
Uploader.File 獲取實例
mounted () {
this.$nextTick(() => {
window.uploader = this.$refs.uploader.uploader
})
}
//實例的調用:
window.uploader.cancel()
.assignBrowse(domNodes, isDirectory, singleFile, attributes)
指定 DOM 元素可以選擇上傳。(用於實現自定義上傳文件/文件夾按鈕,由於使用的框架自帶主題顏色更換,如果使用默認按鈕無法與框架主題色兼容,所以獲取dom后調用此實例方法使自定義的按鈕也具備上傳能力,下方拖拽區域同理)
domNodes
DOM 元素
isDirectory
如果傳入的是 true
則代表是要選擇文件夾上傳的,你可以通過判斷 supportDirectory
來決定是否設置
singleFile
是否只能選擇單個文件
attributes
傳入的其他屬性值,例如你可以傳入 accept
屬性的值為 image/*
,這樣就意味着點選的時候只能選擇圖片。
注意: 避免使用 a
或者 button
標簽作為選擇文件按鈕。
.assignDrop(domNodes)
指定 DOM 元素作為拖拽上傳目標。
.unAssignDrop(domNodes)
取消指定的 DOM 元素作為拖拽上傳目標。
.getRoot()
獲取當前文件所屬的根文件,這個根文件就是包含在 uploader.fileList
中的.
.progress()
返回一個 0 到 1 的數字,代表當前上傳進度。
.pause()
暫停上傳文件。
.resume()
繼續上傳文件。
.cancel()
取消上傳且從文件列表中移除。
.retry()
重新上傳文件。
.bootstrap(
) 重新初始化 Uploader.File
對象的狀態,包括重新分塊,重新創建新的 XMLHttpRequest 實例。
.isUploading()
文件是否仍在上傳中。
.isComplete()
文件是否已經上傳完成。
.sizeUploaded()
已經上傳大小。
.timeRemaining()
剩余時間,基於平均速度的,如果說平均速度為 0,那么值就是 Number.POSITIVE_INFINITY
。
.getExtension()
獲取小寫的后綴。
.getType()
獲取文件類型。
開發遇到的問題
1、上傳文件夾的大致原理本質上還是上傳的文件,只是文件被帶上了文件夾相關的路徑,空文件夾是無法發起請求的,如需完成新建空文件夾的操作需要單獨調用新建文件夾接口完成一個對文件夾表的新增操作。
2、當上傳文件夾時,若文件夾包含子文件夾的情況,由於上傳是異步的,有可能導致上傳的文件夾結構異常或上傳失敗,需要做同步處理,前端有一個並發上傳數的配置應該是前端的同步配置,但是存在部分問題待解決,時間原因,拜托后端對這個上傳做了同步處理解決的。
3、並發上傳數問題,默認給了3個,並發數量改為1就會變成同步上傳,一個一個上傳,按理前端的同步處理就是對這個參數做設置。但是在上傳列表中不會結束已完成的上傳任務,導致一直卡在第一個任務,我是自己手動去移除已完成的任務來解決的這個問題。這個問題自己根據業務調整吧。
4、默認的上傳列表會隨着上傳文件的增多自動撐高,影響了頁面的其他內容,做了一套顯隱處理:存在上傳任務時會出現一個上傳中的圖標,需要點擊圖標才會出現這個脫標的上傳進度框,任務完成后自動清除文件列表,解除上傳中狀態。
1、參考文章1:使用vue-simple-uploader上傳文件和文件夾 作者:月光光
2、參考文章2:simple-uploader.js 功能強大的上傳組件
3、參考文檔3:vue-simple-uploader組件的一些使用心得 作者:隨遇而安丶
4、完整配置項請點此查看: simple-uploader.js github地址及參考文檔