(function () { "use strict"; //service that handles uploading of files and images var serviceId = "fileUpload"; angular .module("app") .factory(serviceId, ["config", "$q", "$upload", "user", fileUpload]); function fileUpload(config, $q, $upload, user) { var service = { uploadFile: uploadFile, uploadImage: uploadImage, }; return service; //upload an image function uploadImage(obj, file, success, progress, error, uploadPath) { user.getProfile().then(function (theUser) { var data = { upload_preset: config.cloudinaryUploadPreset, tags: "myimages," + theUser.id, }; //images are uploaded to Cloudinary $upload .upload({ url: config.cloudinaryApiBaseUrl + config.cloudinaryName + uploadPath, data: data, file: file, }) .progress(function (e) { var percent = Math.round((e.loaded * 100.0) / e.total); return progress(percent); }) .success(function (data, status, headers, config) { return success(obj, data); }) .error(function (data) { return error(); }); }); } //upload a (non-image) file function uploadFile(fileItem, file, success, progress, error, container) { user.getProfile().then(function (theUser) { //upload to azure blob storage return uploadToBlob( fileItem, file, success, progress, error, container ); }); } //get the url of the Azure blob bucket to upload files to function getBucketUploadUrl(fileName, container) { fileName = fileName.replace("#", ""); fileName = fileName.replace(" ", ""); fileName = fileName.replace(")", ""); fileName = fileName.replace("(", ""); // Append timestamp to filename fileName = appendToFilename(fileName, Date.now().toString()); if (container) { return config.azureBlobUrl + container + "/" + fileName; } else { return config.azureBlobUrl + config.uploadBucketName + "/" + fileName; } } function appendToFilename(filename, string) { var dotIndex = filename.lastIndexOf("."); if (dotIndex == -1) return filename + string; else return ( filename.substring(0, dotIndex) + "-" + string + filename.substring(dotIndex) ); } //we use Azure blob storage to upload files to - get the Azure Blob url for the file function getBlobUploadUrl(fileName, container) { //get the base url of blob storage var baseUrl = getBucketUploadUrl(fileName, container); //get the SAS (Secure Access Signature) token from cache (this signature allows us write access permissions to Azure Blob storage - so we can write the file there) var sas = user.getUploadBucketSasCached(); if (sas) { //check if the SAS token is still valid, if it is use the token - using moment.js for easy calculation of times var expiry = moment(sas.expiryTime).subtract("seconds", "30"); //30 seconds to allow for small differences in time calculations between machines if (expiry.isAfter(moment())) { var deferred = $q.defer(); deferred.resolve({ baseUrl: baseUrl, fullUrl: baseUrl + sas.sas }); return deferred.promise; } } if (config.appCode == "OB" || config.appCode == "CUPPA") { return user .getUploadBucketSasForContainerMyUsers(container) .then(function (sas) { return { baseUrl: baseUrl, fullUrl: baseUrl + sas.sas, }; }); } //we don't have a valid existing SAS so get the sas from the server if (container) { return user .getUploadBucketSasForContainer(container) .then(function (sas) { return { baseUrl: baseUrl, fullUrl: baseUrl + sas.sas, }; }); } else { return user.getUploadBucketSas().then(function (sas) { return { baseUrl: baseUrl, fullUrl: baseUrl + sas.sas, }; }); } } //upload the file to blob storage (Azure) function uploadToBlob(fileItem, file, success, progress, error, container) { //first get the upload URL getBlobUploadUrl(fileItem.fileName, container).then(function (urls) { var fileReader = new FileReader(); fileItem.fileUrl = urls.baseUrl; fileItem.isDropBoxFile = false; fileReader.readAsArrayBuffer(file); //use the $upload service to write the file as part of an HTTP PUT request to Azure Blob storage fileReader.onload = function (e) { $upload .http({ url: urls.fullUrl, method: "PUT", headers: { //azure needs these extra headers "x-ms-blob-type": "BlockBlob", "Content-Type": file.type, }, data: e.target.result, }) .progress(function (e) { //inform the user what progress we are making on the upload var percent = Math.round((e.loaded * 100.0) / e.total); return progress(percent); }) .success(function (data, status, headers, config) { return success(fileItem, data); }) .error(function (data) { return error(); }); }; }); } } })();