simple-uploader.js(也稱 Uploader)是一個(gè)上傳庫(kù)既穆,支持多并發(fā)上傳,文件夾雀鹃、拖拽幻工、可暫停繼續(xù)、秒傳黎茎、分塊上傳囊颅、出錯(cuò)自動(dòng)重傳、手工重傳傅瞻、進(jìn)度踢代、剩余時(shí)間、上傳速度等特性嗅骄;該上傳庫(kù)依賴 HTML5 File API胳挎。由于是分塊上傳,所以依賴文件的分塊 API溺森,所以受限于此瀏覽器支持程度為:Firefox 4+, Chrome 11+, Safari 6+ and Internet Explorer 10+慕爬。
Fork flow.js窑眯,但是進(jìn)行了重構(gòu)。
默認(rèn)提供了一個(gè) Node.js 的示例医窿,放在 samples/
目錄下伸但。
相比 flow.js 的新特性
- 統(tǒng)一把文件和文件夾對(duì)待為
Uploader.File
,統(tǒng)一管理 -
Uploader
本身其實(shí)就是一個(gè)根文件夾 - 新增
fileList
屬性留搔,用來(lái)存文件和文件夾合集,只包含根下的文件和文件夾铛铁。
特點(diǎn)
- 支持文件隔显、多文件、文件夾上傳
- 支持拖拽文件饵逐、文件夾上傳
- 統(tǒng)一對(duì)待文件和文件夾括眠,方便操作管理
- 可暫停、繼續(xù)上傳
- 錯(cuò)誤處理
- 支持“快傳”倍权,通過(guò)文件判斷服務(wù)端是否已存在從而實(shí)現(xiàn)“快傳”
- 上傳隊(duì)列管理掷豺,支持最大并發(fā)上傳
- 分塊上傳
- 支持進(jìn)度、預(yù)估剩余時(shí)間薄声、出錯(cuò)自動(dòng)重試当船、重傳等操作
安裝
npm install simple-uploader.js
使用
創(chuàng)建一個(gè) Uploader 實(shí)例:
var uploader = new Uploader({
target: '/api/photo/redeem-upload-token',
query: { upload_token: 'my_token' }
})
// 如果不支持 需要降級(jí)的地方
if (!uploader.support) location.href = '/some-old-crappy-uploader'
如果想要選擇文件或者拖拽文件的話,你可以通過(guò)如下兩個(gè) API 來(lái)指定哪些 DOM 節(jié)點(diǎn):
uploader.assignBrowse(document.getElementById('browseButton'))
uploader.assignDrop(document.getElementById('dropTarget'))
實(shí)例化后你還可以選擇監(jiān)聽(tīng)一些事件:
// 文件添加 單個(gè)文件
uploader.on('fileAdded', function (file, event) {
console.log(file, event)
})
// 單個(gè)文件上傳成功
uploader.on('fileSuccess', function (rootFile, file, message) {
console.log(rootFile, file, message)
})
// 根下的單個(gè)文件(文件夾)上傳完成
uploader.on('fileComplete', function (rootFile) {
console.log(rootFile)
})
// 某個(gè)文件上傳失敗了
uploader.on('fileError', function (rootFile, file, message) {
console.log(rootFile, file, message)
})
服務(wù)端如何接受呢默辨?
因?yàn)樵谇岸俗隽艘恍┓謮K啊等處理德频,所以也需要服務(wù)端做一些特殊處理,這個(gè)可以參考 samples/Node.js/
實(shí)現(xiàn)缩幸。
每一個(gè)上傳塊都會(huì)包含如下分塊信息:
-
chunkNumber
: 當(dāng)前塊的次序壹置,第一個(gè)塊是 1,注意不是從 0 開(kāi)始的表谊。 -
totalChunks
: 文件被分成塊的總數(shù)钞护。 -
chunkSize
: 分塊大小,根據(jù)totalSize
和這個(gè)值你就可以計(jì)算出總共的塊數(shù)爆办。注意最后一塊的大小可能會(huì)比這個(gè)要大难咕。 -
currentChunkSize
: 當(dāng)前塊的大小,實(shí)際大小押逼。 -
totalSize
: 文件總大小步藕。 -
identifier
: 這個(gè)就是每個(gè)文件的唯一標(biāo)示。 -
filename
: 文件名挑格。 -
relativePath
: 文件夾上傳的時(shí)候文件的相對(duì)路徑屬性咙冗。
一個(gè)分塊可以被上傳多次,當(dāng)然這肯定不是標(biāo)準(zhǔn)行為漂彤,但是在實(shí)際上傳過(guò)程中是可能發(fā)生這種事情的雾消,這種重傳也是本庫(kù)的特性之一灾搏。
對(duì)于每個(gè)請(qǐng)求的響應(yīng)碼你都可以根據(jù) successStatuses
和permanentErrors
配置項(xiàng)是否是認(rèn)為成功或失敗的:
-
200
,201
,202
: 當(dāng)前塊上傳成功,不需要重傳立润。 -
404
,415
.500
,501
: 當(dāng)前塊上傳失敗狂窑,會(huì)取消整個(gè)文件上傳。 - 其他狀態(tài)碼: 出錯(cuò)了桑腮,但是會(huì)自動(dòng)重試上傳泉哈。
處理 GET (或者 test() 請(qǐng)求)
如果說(shuō) testChunks
配置項(xiàng)是 true
的話,就可以實(shí)現(xiàn)秒傳破讨、或者刷新頁(yè)面后丛晦、或者重啟瀏覽器、甚至是跨瀏覽器還可以繼續(xù)上傳的效果提陶,所有的上傳必備的參數(shù)數(shù)據(jù)都會(huì)被一并發(fā)出:
- 如果請(qǐng)求返回了
successStatuses
配置的狀態(tài)碼烫沙,那么假定此塊已經(jīng)上傳成功了。 - 如果返回的是
permanentErrors
中的狀態(tài)碼隙笆,那么就認(rèn)為此塊上傳失敗锌蓄。 - 如果是其他狀態(tài)嗎,那么就認(rèn)為服務(wù)端還沒(méi)有這個(gè)塊撑柔,需要按照標(biāo)準(zhǔn)模式上傳瘸爽。
所以有了以上的支持,服務(wù)端就可以根據(jù)預(yù)先發(fā)的這個(gè)請(qǐng)求來(lái)決定是否需要上傳這個(gè)塊內(nèi)容乏冀,所以也就實(shí)現(xiàn)了秒傳或者跨瀏覽器上傳特性蝶糯。
API 文檔
Uploader
配置
實(shí)例化的時(shí)候可以傳入配置項(xiàng):
var r = new Uploader({ opt1: 'val', ...})
支持的配置項(xiàng):
-
target
目標(biāo)上傳 URL,可以是字符串也可以是函數(shù)辆沦,如果是函數(shù)的話昼捍,則會(huì)傳入Uploader.File
實(shí)例、當(dāng)前塊Uploader.Chunk
以及是否是測(cè)試模式肢扯,默認(rèn)值為'/'
妒茬。 -
singleFile
單文件上傳。覆蓋式蔚晨,如果選擇了多個(gè)會(huì)把之前的取消掉乍钻。默認(rèn)false
。 -
chunkSize
分塊時(shí)按照該值來(lái)分铭腕。最后一個(gè)上傳塊的大小是可能是大于等于1倍的這個(gè)值但是小于兩倍的這個(gè)值大小银择,可見(jiàn)這個(gè) Issue #51,默認(rèn)1*1024*1024
累舷。 -
forceChunkSize
是否強(qiáng)制所有的塊都是小于等于chunkSize
的值浩考。默認(rèn)是false
。 -
simultaneousUploads
并發(fā)上傳數(shù)被盈,默認(rèn)3
析孽。 -
fileParameterName
上傳文件時(shí)文件的參數(shù)名搭伤,默認(rèn)file
。 -
query
其他額外的參數(shù)袜瞬,這個(gè)可以是一個(gè)對(duì)象或者是一個(gè)函數(shù)怜俐,如果是函數(shù)的話,則會(huì)傳入Uploader.File
實(shí)例邓尤、當(dāng)前塊Uploader.Chunk
以及是否是測(cè)試模式拍鲤,默認(rèn)為{}
。 -
headers
額外的一些請(qǐng)求頭汞扎,如果是函數(shù)的話殿漠,則會(huì)傳入Uploader.File
實(shí)例、當(dāng)前塊Uploader.Chunk
以及是否是測(cè)試模式佩捞,默認(rèn){}
。 -
withCredentials
標(biāo)準(zhǔn)的 CORS 請(qǐng)求是不會(huì)帶上 cookie 的蕾哟,如果想要帶的話需要設(shè)置withCredentials
為true
一忱,默認(rèn)false
。 -
method
當(dāng)上傳的時(shí)候所使用的是方式谭确,可選multipart
帘营、octet
,默認(rèn)multipart
逐哈,參考 multipart vs octet芬迄。 -
testMethod
測(cè)試的時(shí)候使用的 HTTP 方法,可以是字符串或者函數(shù)昂秃,如果是函數(shù)的話禀梳,則會(huì)傳入Uploader.File
實(shí)例、當(dāng)前塊Uploader.Chunk
肠骆,默認(rèn)GET
算途。 -
uploadMethod
真正上傳的時(shí)候使用的 HTTP 方法,可以是字符串或者函數(shù)蚀腿,如果是函數(shù)的話嘴瓤,則會(huì)傳入Uploader.File
實(shí)例、當(dāng)前塊Uploader.Chunk
莉钙,默認(rèn)POST
廓脆。 -
allowDuplicateUploads
如果說(shuō)一個(gè)文件以及上傳過(guò)了是否還允許再次上傳。默認(rèn)的話如果已經(jīng)上傳了磁玉,除非你移除了否則是不會(huì)再次重新上傳的停忿,所以也就是默認(rèn)值為false
。 -
prioritizeFirstAndLastChunk
對(duì)于文件而言是否高優(yōu)先級(jí)發(fā)送第一個(gè)和最后一個(gè)塊蜀涨。一般用來(lái)發(fā)送到服務(wù)端瞎嬉,然后判斷是否是合法文件蝎毡;例如圖片或者視頻的 meta 數(shù)據(jù)一般放在文件第一部分,這樣可以根據(jù)第一個(gè)塊就能知道是否支持氧枣;默認(rèn)false
沐兵。 -
testChunks
是否測(cè)試每個(gè)塊是否在服務(wù)端已經(jīng)上傳了,主要用來(lái)實(shí)現(xiàn)秒傳便监、跨瀏覽器上傳等扎谎,默認(rèn)true
。 -
preprocess
可選的函數(shù)烧董,每個(gè)塊在測(cè)試以及上傳前會(huì)被調(diào)用毁靶,參數(shù)就是當(dāng)前上傳塊實(shí)例Uploader.Chunk
,注意在這個(gè)函數(shù)中你需要調(diào)用當(dāng)前上傳塊實(shí)例的preprocessFinished
方法逊移,默認(rèn)null
预吆。 -
initFileFn
可選函數(shù)用于初始化文件對(duì)象,傳入的參數(shù)就是Uploader.File
實(shí)例胳泉。 -
readFileFn
可選的函數(shù)用于原始文件的讀取操作拐叉,傳入的參數(shù)就是Uploader.File
實(shí)例、文件類型扇商、開(kāi)始字節(jié)位置 startByte凤瘦,結(jié)束字節(jié)位置 endByte、以及當(dāng)前塊Uploader.Chunk
實(shí)例案铺。并且當(dāng)完成后應(yīng)該調(diào)用當(dāng)前塊實(shí)例的readFinished
方法蔬芥,且?guī)?shù)-已讀取的 bytes。 -
checkChunkUploadedByResponse
可選的函數(shù)用于根據(jù) XHR 響應(yīng)內(nèi)容檢測(cè)每個(gè)塊是否上傳成功了控汉,傳入的參數(shù)是:Uploader.Chunk
實(shí)例以及請(qǐng)求響應(yīng)信息笔诵。這樣就沒(méi)必要上傳(測(cè)試)所有的塊了,具體細(xì)節(jié)原因參考 Issue #1姑子,使用示例. -
generateUniqueIdentifier
可覆蓋默認(rèn)的生成文件唯一標(biāo)示的函數(shù)嗤放,默認(rèn)null
。 -
maxChunkRetries
最大自動(dòng)失敗重試上傳次數(shù)壁酬,值可以是任意正整數(shù)次酌,如果是undefined
則代表無(wú)限次,默認(rèn)0
舆乔。 -
chunkRetryInterval
重試間隔岳服,值可以是任意正整數(shù),如果是null
則代表立即重試希俩,默認(rèn)null
吊宋。 -
progressCallbacksInterval
進(jìn)度回調(diào)間隔,默認(rèn)是500
颜武。 -
speedSmoothingFactor
主要用于計(jì)算平均速度璃搜,值就是從 0 到 1拖吼,如果是 1 那么上傳的平均速度就等于當(dāng)前上傳速度,如果說(shuō)長(zhǎng)時(shí)間上傳的話这吻,建議設(shè)置為0.02
吊档,這樣剩余時(shí)間預(yù)估會(huì)更精確,這個(gè)參數(shù)是需要和progressCallbacksInterval
一起調(diào)整的唾糯,默認(rèn)是0.1
怠硼。 -
successStatuses
認(rèn)為響應(yīng)式成功的響應(yīng)碼,默認(rèn)[200, 201, 202]
移怯。 -
permanentErrors
認(rèn)為是出錯(cuò)的響應(yīng)碼香璃,默認(rèn)[404, 415, 500, 501]
。 -
initialPaused
初始文件 paused 狀態(tài)舟误,默認(rèn)false
葡秒。 -
processResponse
處理請(qǐng)求結(jié)果,默認(rèn)function (response, cb) { cb(null, response) }
嵌溢。 0.5.2版本后同云,processResponse
會(huì)傳入更多參數(shù):(response, cb, Uploader.File, Uploader.Chunk)。 -
processParams
處理請(qǐng)求參數(shù)堵腹,默認(rèn)function (params) {return params}
,一般用于修改參數(shù)名字或者刪除參數(shù)星澳。0.5.2版本后疚顷,processParams
會(huì)有更多參數(shù):(params, Uploader.File, Uploader.Chunk, isTest)。
屬性
-
.support
當(dāng)前瀏覽器是否支持 File API 來(lái)上傳禁偎。 -
.supportDirectory
當(dāng)前瀏覽器是否支持文件夾上傳腿堤。 -
.opts
實(shí)例的配置項(xiàng)對(duì)象。 -
.files
由Uploader.File
文件對(duì)象組成的數(shù)組如暖,純文件列表笆檀。 -
.fileList
由Uploader.File
文件、文件夾對(duì)象組成的數(shù)組盒至,文件和文件夾共存酗洒。
方法
-
.assignBrowse(domNodes, isDirectory, singleFile, attributes)
指定 DOM 元素可以選擇上傳。-
domNodes
DOM 元素 -
isDirectory
如果傳入的是true
則代表是要選擇文件夾上傳的枷遂,你可以通過(guò)判斷supportDirectory
來(lái)決定是否設(shè)置 -
singleFile
是否只能選擇單個(gè)文件 -
attributes
傳入的其他屬性值樱衷,例如你可以傳入accept
屬性的值為image/*
,這樣就意味著點(diǎn)選的時(shí)候只能選擇圖片酒唉。全部屬性列表:https://www.w3.org/wiki/HTML/Elements/input/file
Note: 避免使用
a
或者button
標(biāo)簽作為選擇文件按鈕矩桂。 -
.assignDrop(domNodes)
指定 DOM 元素作為拖拽上傳目標(biāo)。.unAssignDrop(domNodes)
取消指定的 DOM 元素作為拖拽上傳目標(biāo)痪伦。.on(event, callback)
監(jiān)聽(tīng)事件侄榴。-
.off([event, [callback]])
:-
.off(event)
移除指定事件的所有事件回調(diào) -
.off(event, callback)
移除指定事件的指定回調(diào)雹锣。callback
是一個(gè)函數(shù)
-
.upload()
開(kāi)始或者繼續(xù)上傳。.pause()
暫停上傳癞蚕。.resume()
繼續(xù)上傳蕊爵。.cancel()
取消所有上傳文件,文件會(huì)被移除掉涣达。.progress()
返回一個(gè)0-1的浮點(diǎn)數(shù)在辆,當(dāng)前上傳進(jìn)度。.isUploading()
返回一個(gè)布爾值標(biāo)示是否還有文件正在上傳中度苔。.addFile(file)
添加一個(gè)原生的文件對(duì)象到上傳列表中匆篓。.removeFile(file)
從上傳列表中移除一個(gè)指定的Uploader.File
實(shí)例對(duì)象。.getFromUniqueIdentifier(uniqueIdentifier)
根據(jù)唯一標(biāo)識(shí)找到Uploader.File
實(shí)例寇窑。.getSize()
上傳文件的總大小鸦概。.sizeUploaded()
所有已經(jīng)成功上傳文件大小。.timeRemaining()
剩余時(shí)間甩骏,單位秒窗市;這個(gè)是基于平均上傳速度計(jì)算出來(lái)的,如果說(shuō)上傳速度為 0饮笛,那么這個(gè)值就是Number.POSITIVE_INFINITY
咨察。
事件
-
.change(event)
input 的 change 事件。 -
.dragover(event)
拖拽區(qū)域的 dragover 事件福青。 -
.dragenter(event)
拖拽區(qū)域的 dragenter 事件摄狱。 -
.dragleave(event)
拖拽區(qū)域的 dragleave 事件。 -
.fileSuccess(rootFile, file, message, chunk)
一個(gè)文件上傳成功事件无午,第一個(gè)參數(shù)rootFile
就是成功上傳的文件所屬的根Uploader.File
對(duì)象媒役,它應(yīng)該包含或者等于成功上傳文件;第二個(gè)參數(shù)file
就是當(dāng)前成功的Uploader.File
對(duì)象本身宪迟;第三個(gè)參數(shù)就是message
就是服務(wù)端響應(yīng)內(nèi)容酣衷,永遠(yuǎn)都是字符串;第四個(gè)參數(shù)chunk
就是Uploader.Chunk
實(shí)例次泽,它就是該文件的最后一個(gè)塊實(shí)例穿仪,如果你想得到請(qǐng)求響應(yīng)碼的話,chunk.xhr.status
就是意荤。 -
.fileComplete(rootFile)
一個(gè)根文件(文件夾)成功上傳完成牡借。 -
.fileProgress(rootFile, file, chunk)
一個(gè)文件在上傳中。 -
.fileAdded(file, event)
這個(gè)事件一般用作文件校驗(yàn)袭异,如果說(shuō)返回了false
钠龙,那么這個(gè)文件就會(huì)被忽略,不會(huì)添加到文件上傳列表中。 -
.filesAdded(files, fileList, event)
和 fileAdded 一樣碴里,但是一般用作多個(gè)文件的校驗(yàn)沈矿。 -
.filesSubmitted(files, fileList, event)
和 filesAdded 類似,但是是文件已經(jīng)加入到上傳列表中咬腋,一般用來(lái)開(kāi)始整個(gè)的上傳羹膳。 -
.fileRemoved(file)
一個(gè)文件(文件夾)被移除。 -
.fileRetry(rootFile, file, chunk)
文件重試上傳事件根竿。 -
.fileError(rootFile, file, message, chunk)
上傳過(guò)程中出錯(cuò)了陵像。 -
.uploadStart()
已經(jīng)開(kāi)始上傳了。 -
.complete()
上傳完畢寇壳。 -
.catchAll(event, ...)
所有的事件醒颖。
Uploader.File
屬性
-
.uploader
對(duì)Uploader
實(shí)例的引用。 -
.name
文件(夾)名字壳炎。 -
.averageSpeed
平均速度泞歉,單位字節(jié)每秒。 -
.currentSpeed
當(dāng)前速度匿辩,單位字節(jié)每秒腰耙。 -
.paused
文件是否是暫停的。 -
.error
文件上傳是否出錯(cuò)了。 -
.isFolder
是否是文件夾。
如果不是文件夾的話,那么還會(huì)有如下屬性:
-
.file
原生 HTML5File
對(duì)象。 -
.relativePath
文件相對(duì)路徑侯繁。 -
.size
文件大小,單位字節(jié)。 -
.uniqueIdentifier
文件唯一標(biāo)示。 -
.chunks
由Uploader.Chunk
實(shí)例組成數(shù)組,分成的塊集合锨用,一般場(chǎng)景下并不需要關(guān)心它丰刊。
方法
-
.getRoot()
得到當(dāng)前文件所屬的根文件,這個(gè)根文件就是包含在uploader.fileList
中的. -
.progress()
返回一個(gè) 0 到 1 的數(shù)字增拥,代表當(dāng)前上傳進(jìn)度啄巧。 -
.pause()
暫停上傳文件。 -
.resume()
繼續(xù)上傳文件掌栅。 -
.cancel()
取消上傳且從文件列表中移除秩仆。 -
.retry()
重新上傳文件。 -
.bootstrap()
重新初始化Uploader.File
對(duì)象的狀態(tài)猾封,包括重新分塊澄耍,重新創(chuàng)建新的 XMLHttpRequest 實(shí)例。 -
.isUploading()
文件是否扔在上傳中。 -
.isComplete()
文件是否已經(jīng)上傳完成齐莲。 -
.sizeUploaded()
已經(jīng)上傳大小痢站。 -
.timeRemaining()
剩余時(shí)間,基于平均速度的选酗,如果說(shuō)平均速度為 0阵难,那么值就是Number.POSITIVE_INFINITY
。 -
.getExtension()
得到小寫的后綴芒填。 -
.getType()
得到文件類型呜叫。
源
simple-uploader.js 是 FORK 的 https://github.com/flowjs/flow.js 的,參考了 https://github.com/23/resumable.js殿衰。