diff --git a/src/oss-js-upload.js b/src/oss-js-upload.js index 0b2e42d..e44ce72 100644 --- a/src/oss-js-upload.js +++ b/src/oss-js-upload.js @@ -1,336 +1,334 @@ 'use strict'; -(function () { - - var detectIEVersion = function () { - var v = 4, - div = document.createElement('div'), - all = div.getElementsByTagName('i'); - while ( - div.innerHTML = '', +(function() { + + var detectIEVersion = function() { + var v = 4, + div = document.createElement('div'), + all = div.getElementsByTagName('i'); + while ( + div.innerHTML = '', all[0] ) { - v++; - } - return v > 4 ? v : false; - }; - - var _extend = function (dst, src) { - for (var i in src) { - if (Object.prototype.hasOwnProperty.call(src, i) && src[i]) { - dst[i] = src[i]; - } - } - }; - - function OssUpload(config) { - if (!config) { - // console.log('需要 config'); - return; - } - this._config = { - chunkSize: 1048576 // 1MB - }; - - if (this._config.chunkSize && this._config.chunkSize < 102400) { - // console.log('chunkSize 不能小于 100KB'); - return; - } - - _extend(this._config, config); - - if (!this._config.aliyunCredential && !this._config.stsToken) { - // console.log('需要 stsToken'); - return; - } - - if (!this._config.endpoint) { - // console.log('需要 endpoint'); - return; - } - - var ALY = window.ALY; - if (this._config.stsToken) { - this.oss = new ALY.OSS({ - accessKeyId: this._config.stsToken.Credentials.AccessKeyId, - secretAccessKey: this._config.stsToken.Credentials.AccessKeySecret, - securityToken: this._config.stsToken.Credentials.SecurityToken, - endpoint: this._config.endpoint, - apiVersion: '2013-10-15' - }); - } - else { - this.oss = new ALY.OSS({ - accessKeyId: this._config.aliyunCredential.accessKeyId, - secretAccessKey: this._config.aliyunCredential.secretAccessKey, - endpoint: this._config.endpoint, - apiVersion: '2013-10-15' - }); - } - - var arr = this._config.endpoint.split('://'); - if (arr.length < 2) { - // console.log('endpoint 格式错误'); - return; - } - this._config.endpoint = { - protocol: arr[0], - host: arr[1] - } - - } - - OssUpload.prototype.upload = function (options) { - if (!options) { - if (typeof options.onerror == 'function') { - options.onerror('需要 options'); - } - return; - } - - if (!options.file) { - if (typeof options.onerror == 'function') { - options.onerror('需要 file'); - } - return; - } - var file = options.file; - - if (!options.key) { - if (typeof options.onerror == 'function') { - options.onerror('需要 key'); - } - return; - } - // 去掉 key 开头的 / - options.key.replace(new RegExp("^\/"), ''); - - var self = this; - - var readFile = function (callback) { - var result = { - chunksHash: {}, - chunks: [] - }; - var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; - var chunkSize = self._config.chunkSize; - var chunksNum = Math.ceil(file.size / chunkSize); - var currentChunk = 0; - - var frOnload = function (e) { - result.chunks[currentChunk] = e.target.result; - currentChunk++; - if (currentChunk < chunksNum) { - loadNext(); - } - else { - result.file_size = file.size; - callback(null, result); + v++; } - }; - var frOnerror = function () { - console.error("读取文件失败"); - if (typeof options.onerror == 'function') { - options.onerror("读取文件失败"); - } - }; - - function loadNext() { - var fileReader = new FileReader(); - fileReader.onload = frOnload; - fileReader.onerror = frOnerror; - - var start = currentChunk * chunkSize, - end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize; - var blobPacket = blobSlice.call(file, start, end); - fileReader.readAsArrayBuffer(blobPacket); - } - - loadNext(); + return v > 4 ? v : false; }; - var uploadSingle = function (result, callback) { - var params = { - Bucket: self._config.bucket, - Key: options.key, - Body: result.chunks[0], - ContentType: file.type || '' - }; - _extend(params, options.headers); - - var req = self.oss.putObject(params, callback); - - req.on('httpUploadProgress', function(p) { - if (typeof options.onprogress == 'function') { - options.onprogress({ - loaded: p.loaded, - total: file.size - }); + var _extend = function(dst, src) { + for (var i in src) { + if (Object.prototype.hasOwnProperty.call(src, i) && src[i]) { + dst[i] = src[i]; + } } - }); }; - var uploadMultipart = function (result, callback) { - var maxUploadTries = options.maxRetry || 3; - var uploadId; - var loadedNum = 0; - var latestUploadNum = -1; - var concurrency = 0; - - var multipartMap = { - Parts: [] - }; - - var init = function () { - var params = { - Bucket: self._config.bucket, - Key: options.key, - ContentType: file.type || '' + function OssUpload(config) { + if (!config) { + // console.log('需要 config'); + return; + } + this._config = { + chunkSize: 1048576 // 1MB }; - _extend(params, options.headers); - self.oss.createMultipartUpload(params, - function (mpErr, res) { - if (mpErr) { - // console.log('Error!', mpErr); - callback(mpErr); - return; - } - - // console.log("Got upload ID", res.UploadId); - uploadId = res.UploadId; + if (this._config.chunkSize && this._config.chunkSize < 102400) { + // console.log('chunkSize 不能小于 100KB'); + return; + } - uploadPart(0); - }); - }; + _extend(this._config, config); - var uploadPart = function (partNum) { - if(partNum >= result.chunks.length) { - return; + if (!this._config.aliyunCredential && !this._config.stsToken) { + // console.log('需要 stsToken'); + return; } - concurrency++; - if(latestUploadNum < partNum) { - latestUploadNum = partNum; + if (!this._config.endpoint) { + // console.log('需要 endpoint'); + return; } - if(concurrency < self._config.concurrency && (partNum < (result.chunks.length - 1))) { - uploadPart(partNum + 1); + + var ALY = window.ALY; + if (this._config.stsToken) { + this.oss = new ALY.OSS({ + accessKeyId: this._config.stsToken.Credentials.AccessKeyId, + secretAccessKey: this._config.stsToken.Credentials.AccessKeySecret, + securityToken: this._config.stsToken.Credentials.SecurityToken, + endpoint: this._config.endpoint, + apiVersion: '2013-10-15' + }); + } else { + this.oss = new ALY.OSS({ + accessKeyId: this._config.aliyunCredential.accessKeyId, + secretAccessKey: this._config.aliyunCredential.secretAccessKey, + endpoint: this._config.endpoint, + apiVersion: '2013-10-15' + }); } - var partParams = { - Body: result.chunks[partNum], - Bucket: self._config.bucket, - Key: options.key, - PartNumber: String(partNum + 1), - UploadId: uploadId - }; - var tryNum = 1; - - var doUpload = function () { - - multipartMap.Parts[partNum] = { - PartNumber: partNum + 1, - loaded: 0 - }; - - var req = self.oss.uploadPart(partParams, function (multiErr, mData) { - if (multiErr) { - // console.log('multiErr, upload part error:', multiErr); - if (tryNum > maxUploadTries) { - console.log('上传分片失败: #', partParams.PartNumber); - callback(multiErr); - } - else { - console.log('重新上传分片: #', partParams.PartNumber); - multipartMap.Parts[partNum].loaded = 0; - tryNum++; - doUpload(); - } - return; - } + var arr = this._config.endpoint.split('://'); + if (arr.length < 2) { + // console.log('endpoint 格式错误'); + return; + } + this._config.endpoint = { + protocol: arr[0], + host: arr[1] + } - multipartMap.Parts[partNum].ETag = mData.ETag; - multipartMap.Parts[partNum].loaded = partParams.Body.byteLength; + } - // console.log(mData); - concurrency--; + OssUpload.prototype.upload = function(options) { + if (!options) { + if (typeof options.onerror == 'function') { + options.onerror('需要 options'); + } + return; + } - console.log("Completed part", partNum + 1); - //console.log('mData', mData); + if (!options.file) { + if (typeof options.onerror == 'function') { + options.onerror('需要 file'); + } + return; + } + var file = options.file; - loadedNum++; - if (loadedNum == result.chunks.length) { - complete(); + if (!options.key) { + if (typeof options.onerror == 'function') { + options.onerror('需要 key'); } - else { - uploadPart(latestUploadNum + 1); + return; + } + // 去掉 key 开头的 / + options.key.replace(new RegExp("^\/"), ''); + + var self = this; + + var readFile = function(callback) { + var result = { + chunksHash: {}, + chunks: [] + }; + var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; + var chunkSize = self._config.chunkSize; + var chunksNum = Math.ceil(file.size / chunkSize); + var currentChunk = 0; + + var frOnload = function(e) { + result.chunks[currentChunk] = e.target.result; + currentChunk++; + if (currentChunk < chunksNum) { + loadNext(); + } else { + result.file_size = file.size; + callback(null, result); + } + }; + var frOnerror = function() { + console.error("读取文件失败"); + if (typeof options.onerror == 'function') { + options.onerror("读取文件失败"); + } + }; + + function loadNext() { + var fileReader = new FileReader(); + fileReader.onload = frOnload; + fileReader.onerror = frOnerror; + + var start = currentChunk * chunkSize, + end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize; + var blobPacket = blobSlice.call(file, start, end); + fileReader.readAsArrayBuffer(blobPacket); } - }); - req.on('httpUploadProgress', function(p) { - multipartMap.Parts[partNum].loaded = p.loaded; + loadNext(); + }; - var loaded = 0; - for(var i in multipartMap.Parts) { - loaded += multipartMap.Parts[i].loaded; - } + var uploadSingle = function(result, callback) { + var params = { + Bucket: self._config.bucket, + Key: options.key, + Body: result.chunks[0], + ContentType: file.type || '' + }; + _extend(params, options.headers); + + var req = self.oss.putObject(params, function(err, data) { + data.Location = self._config.endpoint.protocol + '://' + params.Bucket + '.' + self._config.endpoint.host + '/' + params.Key; + callback(err, data); + }); - if (typeof options.onprogress == 'function') { - options.onprogress({ - loaded: loaded, - total: file.size - }); - } - }); + req.on('httpUploadProgress', function(p) { + if (typeof options.onprogress == 'function') { + options.onprogress({ + loaded: p.loaded, + total: file.size + }); + } + }); }; - doUpload(); + var uploadMultipart = function(result, callback) { + var maxUploadTries = options.maxRetry || 3; + var uploadId; + var loadedNum = 0; + var latestUploadNum = -1; + var concurrency = 0; + + var multipartMap = { + Parts: [] + }; + + var init = function() { + var params = { + Bucket: self._config.bucket, + Key: options.key, + ContentType: file.type || '' + }; + _extend(params, options.headers); + + self.oss.createMultipartUpload(params, + function(mpErr, res) { + if (mpErr) { + // console.log('Error!', mpErr); + callback(mpErr); + return; + } + + // console.log("Got upload ID", res.UploadId); + uploadId = res.UploadId; + + uploadPart(0); + }); + }; + + var uploadPart = function(partNum) { + if (partNum >= result.chunks.length) { + return; + } + + concurrency++; + if (latestUploadNum < partNum) { + latestUploadNum = partNum; + } + if (concurrency < self._config.concurrency && (partNum < (result.chunks.length - 1))) { + uploadPart(partNum + 1); + } + var partParams = { + Body: result.chunks[partNum], + Bucket: self._config.bucket, + Key: options.key, + PartNumber: String(partNum + 1), + UploadId: uploadId + }; + + var tryNum = 1; + + var doUpload = function() { + + multipartMap.Parts[partNum] = { + PartNumber: partNum + 1, + loaded: 0 + }; + + var req = self.oss.uploadPart(partParams, function(multiErr, mData) { + if (multiErr) { + // console.log('multiErr, upload part error:', multiErr); + if (tryNum > maxUploadTries) { + console.log('上传分片失败: #', partParams.PartNumber); + callback(multiErr); + } else { + console.log('重新上传分片: #', partParams.PartNumber); + multipartMap.Parts[partNum].loaded = 0; + tryNum++; + doUpload(); + } + return; + } + + multipartMap.Parts[partNum].ETag = mData.ETag; + multipartMap.Parts[partNum].loaded = partParams.Body.byteLength; + + // console.log(mData); + concurrency--; + + console.log("Completed part", partNum + 1); + //console.log('mData', mData); + + loadedNum++; + if (loadedNum == result.chunks.length) { + complete(); + } else { + uploadPart(latestUploadNum + 1); + } + }); + + req.on('httpUploadProgress', function(p) { + multipartMap.Parts[partNum].loaded = p.loaded; + + var loaded = 0; + for (var i in multipartMap.Parts) { + loaded += multipartMap.Parts[i].loaded; + } + + if (typeof options.onprogress == 'function') { + options.onprogress({ + loaded: loaded, + total: file.size + }); + } + }); + }; - }; - - var complete = function () { - // console.log("Completing upload..."); + doUpload(); - for(var i in multipartMap.Parts) { - delete multipartMap.Parts[i].loaded; - } + }; - var doneParams = { - Bucket: self._config.bucket, - Key: options.key, - CompleteMultipartUpload: multipartMap, - UploadId: uploadId - }; + var complete = function() { + // console.log("Completing upload..."); - self.oss.completeMultipartUpload(doneParams, callback); - }; + for (var i in multipartMap.Parts) { + delete multipartMap.Parts[i].loaded; + } - init(); - }; + var doneParams = { + Bucket: self._config.bucket, + Key: options.key, + CompleteMultipartUpload: multipartMap, + UploadId: uploadId + }; - readFile(function (err, result) { - var callback = function (err, res) { - if (err) { - if (typeof options.onerror == 'function') { - options.onerror(err); - } - return; - } + self.oss.completeMultipartUpload(doneParams, callback); + }; - if (typeof options.oncomplete == 'function') { - options.oncomplete(res); - } - }; + init(); + }; - if (result.chunks.length == 1) { - uploadSingle(result, callback) - } - else { - uploadMultipart(result, callback); - } - }); + readFile(function(err, result) { + var callback = function(err, res) { + if (err) { + if (typeof options.onerror == 'function') { + options.onerror(err); + } + return; + } + + if (typeof options.oncomplete == 'function') { + options.oncomplete(res); + } + }; + + if (result.chunks.length == 1) { + uploadSingle(result, callback) + } else { + uploadMultipart(result, callback); + } + }); - }; + }; - window.OssUpload = OssUpload; + window.OssUpload = OssUpload; -})(); +})(); \ No newline at end of file