Uploader.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. "use strict";
  2. /**
  3. * Licensed Materials - Property of IBM
  4. * IBM Cognos Products: Cognos Analytics
  5. * Copyright IBM Corp. 2016, 2019
  6. * US Government Users Restricted Rights - Use, duplication or disclosure
  7. * restricted by GSA ADP Schedule Contract with IBM Corp.
  8. */
  9. define(['underscore', 'bi/glass/core/Class', 'bi/admin/nls/StringResource', 'bi/glass/common/ui/ProgressToast'], function (_, Class, StringResource, ProgressToast) {
  10. 'use strict'; //NOSONAR: meant to be strict
  11. var Uploader = Class.extend({
  12. includeFileName: false,
  13. /**
  14. *@options.glassContext - glassContext
  15. *@options.$el - Container
  16. *@options.ajax() - ajax function to upload data
  17. *@options.ajaxOptions
  18. */
  19. init: function init(options) {
  20. Uploader.inherited('init', this, arguments);
  21. _.extend(this, options);
  22. },
  23. /**
  24. * For testing purposes
  25. */
  26. _getWindow: function _getWindow() {
  27. return window;
  28. },
  29. /**
  30. * For testing purposes
  31. */
  32. _getNavigator: function _getNavigator() {
  33. return navigator;
  34. },
  35. /**
  36. * Starting point for using uploader. Prompts user to select a file from browser/OS file selector
  37. */
  38. doUpload: function doUpload() {
  39. return new Promise(function (resolve, reject) {
  40. var application = this.glassContext.appController;
  41. if (!this._getWindow().File || !this._getWindow().FileReader || !this._getWindow().FileList || !this._getWindow().Blob) {
  42. application.showErrorMessage(StringResource.get('errorHTML5Support'), StringResource.get('error'));
  43. reject();
  44. } else if (/^((?!chrome).)*safari\/537/i.test(this._getNavigator().userAgent)) {
  45. application.showErrorMessage(StringResource.get('errorUploadSupport'), StringResource.get('error'));
  46. reject();
  47. } else {
  48. this._removeInput();
  49. var $input = this._getInput();
  50. this.$el.append($input);
  51. $input.change(function (e) {
  52. this._verifyAndUpload(e).then(resolve, reject);
  53. }.bind(this)); // hack: this is for functional testing purpose to stop prompting with the browser file picker
  54. if (!document.getElementById('skipInvokingFileSelectionAdmin')) {
  55. $input.click();
  56. }
  57. }
  58. }.bind(this));
  59. },
  60. _getBaseInputOptions: function _getBaseInputOptions() {
  61. return {
  62. 'type': 'file',
  63. 'id': 'idUploadUIElement',
  64. 'name': 'uploadfiles',
  65. 'style': 'display: none;',
  66. 'multiple': false
  67. };
  68. },
  69. _getInput: function _getInput() {
  70. var inputOptions = this._getBaseInputOptions();
  71. if (this.fileType && this.fileType === 'csv') {
  72. inputOptions.accept = '.csv';
  73. } else {
  74. inputOptions.accept = 'application/zip';
  75. }
  76. return $('<input>', inputOptions);
  77. },
  78. _verifyAndUpload: function _verifyAndUpload(evt) {
  79. return Promise.try(function () {
  80. var currFile = evt.target.files[0];
  81. var configMaxSize = 500;
  82. var maxFileSizeInByte = configMaxSize * 1024 * 1024;
  83. var errMsg;
  84. if (_.isUndefined(currFile.size) || currFile.size > maxFileSizeInByte) {
  85. errMsg = StringResource.get('msgHardLimitFileUpload', {
  86. 'message': configMaxSize
  87. });
  88. this.glassContext.appController.showErrorMessage(errMsg, StringResource.get('error'));
  89. } else if (!this._isValidFileName(currFile.name)) {
  90. errMsg = this._getInvalidFileNameMessage();
  91. this.glassContext.appController.showErrorMessage(errMsg, StringResource.get('msgFileNameUploadTitle'));
  92. } else {
  93. return this._uploadProcessor(currFile);
  94. }
  95. throw new Error(errMsg);
  96. }.bind(this));
  97. },
  98. _isValidFileName: function _isValidFileName(fileName) {
  99. if (this.fileType === 'csv') {
  100. return /^[a-z0-9_ \-\.]{1,200}\.csv$/i.test(fileName);
  101. } else {
  102. return /^[a-z0-9_ \-\.]{1,200}\.zip$/i.test(fileName);
  103. }
  104. },
  105. // NB - the message returned should match regexp above
  106. _getInvalidFileNameMessage: function _getInvalidFileNameMessage() {
  107. return StringResource.get('msgFileNameUpload');
  108. },
  109. /**
  110. * For testing purposes
  111. */
  112. _createFileReader: function _createFileReader() {
  113. return new FileReader();
  114. },
  115. /**
  116. * For testing purposes
  117. */
  118. _createProgressToast: function _createProgressToast() {
  119. return new ProgressToast();
  120. },
  121. _uploadProcessor: function _uploadProcessor(currFile) {
  122. return new Promise(function (resolve, reject) {
  123. this.progressBar = this._createProgressToast();
  124. var reader = this._createFileReader();
  125. this.progressBar.show(StringResource.get('msgUploadStarted'));
  126. this.progressBar.progress();
  127. this.progressBar.onCancel(function () {
  128. try {
  129. reader.abort();
  130. } catch (e) {
  131. return;
  132. }
  133. }.bind(this));
  134. reader.onerror = function () {
  135. this.progressBar.fail(StringResource.get('errorReadingFile'));
  136. reject();
  137. }.bind(this);
  138. reader.onabort = function () {
  139. this.progressBar.fail(StringResource.get('abortReadingFile'));
  140. reject();
  141. }.bind(this);
  142. reader.onprogress = function (e) {
  143. var percentLoaded = Math.round(e.loaded / e.total * 100);
  144. this.progressBar.setComplete(percentLoaded);
  145. }.bind(this);
  146. reader.onload = function (e) {
  147. this._readerOnload(currFile.name, e).then(resolve, reject);
  148. }.bind(this);
  149. reader.readAsArrayBuffer(currFile);
  150. }.bind(this));
  151. },
  152. _readerOnload: function _readerOnload(fileName, e) {
  153. this.progressBar.indefinite(StringResource.get('msgUploadToServer'));
  154. var options = {
  155. 'data': e.target.result,
  156. 'byteLength': e.target.result.byteLength
  157. };
  158. if (this.includeFileName) {
  159. options.fileName = this._getFileName(fileName, e);
  160. }
  161. _.extend(options, this.ajaxOptions);
  162. return this.ajax(options).then(function () {
  163. this.progressBar.setComplete(100, {
  164. isComplete: true,
  165. completeMsg: StringResource.get('msgFileUploadSuccess')
  166. });
  167. }.bind(this), function (err) {
  168. if (err.jqXHR) {
  169. var jqXHR = err.jqXHR;
  170. if (!_.isUndefined(jqXHR.responseJSON) && !_.isUndefined(jqXHR.responseJSON.errors)) {
  171. var errors = jqXHR.responseJSON.errors;
  172. if (errors.length > 0) {
  173. this.glassContext.appController.showErrorMessage(errors[0].message, errors[0].code);
  174. }
  175. }
  176. }
  177. this.progressBar.remove("");
  178. throw jqXHR;
  179. }.bind(this));
  180. },
  181. _removeInput: function _removeInput() {
  182. this.$el.find('input#idUploadUIElement').remove();
  183. },
  184. _getFileName: function _getFileName(fileName, e) {
  185. return fileName;
  186. }
  187. });
  188. return Uploader;
  189. });