UNPKG

vue-azure-blob-upload

Version:

VueJS service for multi-part uploading to MS Azure blob storage.

184 lines (154 loc) 6.02 kB
/**! * VueJS Azure blob upload service * @author Andrzej Ojczenasz - email: codelaborer@gmail.com * @version 0.0.1 * based on: * AngularJS Azure blob upload service with http post and progress. * by Stephen Brannan - twitter: @kinstephen */ var azureBlob = function ($log, $http) { var DefaultBlockSize = 1024 * 32 // Default to 32KB /* config: { baseUrl: // baseUrl for blob file uri (i.e. http://<accountName>.blob.core.windows.net/<container>/<blobname>), sasToken: // Shared access signature querystring key/value prefixed with ?, file: // File object using the HTML5 File API, progress: // progress callback function, complete: // complete callback function, error: // error callback function, blockSize: // Use this to override the DefaultBlockSize } */ var upload = function (config, httpClient) { var state = initializeState(config); // custom Http client if (httpClient) { $http = httpClient; $log('custom http client enabled!'); } var reader = new FileReader(); reader.onloadend = function (evt) { if (evt.target.readyState == FileReader.DONE && !state.cancelled) { // DONE == 2 var uri = state.fileUrl + '&comp=block&blockid=' + state.blockIds[state.blockIds.length - 1]; var requestData = new Uint8Array(evt.target.result); $log(uri); $http.put(uri, requestData, { headers: { 'x-ms-blob-type': 'BlockBlob', 'Content-Type': state.file.type, }, transformRequest: [], }).then(function (response) { $log(response.data); $log(response.status); state.bytesUploaded += requestData.length; var percentComplete = ((parseFloat(state.bytesUploaded) / parseFloat(state.file.size)) * 100).toFixed(2); if (state.progress) state.progress(percentComplete, response.data, response.status, response.headers, response.config); uploadFileInBlocks(reader, state); }, function (response) { $log(response.data); $log(response.status); if (state.error) state.error(response.data, response.status, response.headers, response.config); }); } }; uploadFileInBlocks(reader, state); return { cancel: function () { state.cancelled = true; } }; }; var initializeState = function (config) { var blockSize = DefaultBlockSize; if (config.blockSize) blockSize = config.blockSize; var maxBlockSize = blockSize; // Default Block Size var numberOfBlocks = 1; var file = config.file; var fileSize = file.size; if (fileSize < blockSize) { maxBlockSize = fileSize; $log("max block size = " + maxBlockSize); } if (fileSize % maxBlockSize == 0) { numberOfBlocks = fileSize / maxBlockSize; } else { numberOfBlocks = parseInt(fileSize / maxBlockSize, 10) + 1; } $log("total blocks = " + numberOfBlocks); return { maxBlockSize: maxBlockSize, //Each file will be split in 256 KB. numberOfBlocks: numberOfBlocks, totalBytesRemaining: fileSize, currentFilePointer: 0, blockIds: new Array(), blockIdPrefix: 'block-', bytesUploaded: 0, submitUri: null, file: file, baseUrl: config.baseUrl, sasToken: config.sasToken, fileUrl: config.baseUrl + config.sasToken, progress: config.progress, complete: config.complete, error: config.error, cancelled: false }; }; var uploadFileInBlocks = function (reader, state) { if (!state.cancelled) { if (state.totalBytesRemaining > 0) { $log("current file pointer = " + state.currentFilePointer + " bytes read = " + state.maxBlockSize); var fileContent = state.file.slice(state.currentFilePointer, state.currentFilePointer + state.maxBlockSize); var blockId = state.blockIdPrefix + pad(state.blockIds.length, 6); $log("block id = " + blockId); state.blockIds.push(btoa(blockId)); reader.readAsArrayBuffer(fileContent); state.currentFilePointer += state.maxBlockSize; state.totalBytesRemaining -= state.maxBlockSize; if (state.totalBytesRemaining < state.maxBlockSize) { state.maxBlockSize = state.totalBytesRemaining; } } else { commitBlockList(state); } } }; var commitBlockList = function (state) { var uri = state.fileUrl + '&comp=blocklist'; $log(uri); var requestBody = '<?xml version="1.0" encoding="utf-8"?><BlockList>'; for (var i = 0; i < state.blockIds.length; i++) { requestBody += '<Latest>' + state.blockIds[i] + '</Latest>'; } requestBody += '</BlockList>'; $log(requestBody); $http.put(uri, requestBody, { headers: { 'x-ms-blob-content-type': state.file.type, } }).then(function (response) { $log(response.data); $log(response.status); if (state.complete) state.complete(response.data, response.status, response.headers, response.config); }, function (response) { $log(response.data); $log(response.status); if (state.error) state.error(response.data, response.status, response.headers, response.config); }); }; var pad = function (number, length) { var str = '' + number; while (str.length < length) { str = '0' + str; } return str; }; return upload; } azureBlob.install = function (Vue, options) { Vue.prototype.$log = console.log.bind(console); // Vue instance method declaration Vue.prototype.$azureUpload = this.call('upload', Vue.prototype.$log, Vue.$http); } export default azureBlob;