ParseFile.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
  7. var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
  8. var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
  9. var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
  10. var _CoreManager = _interopRequireDefault(require("./CoreManager"));
  11. var ParseError = require('./ParseError').default;
  12. var XHR = null;
  13. if (typeof XMLHttpRequest !== 'undefined') {
  14. XHR = XMLHttpRequest;
  15. }
  16. function b64Digit(number) {
  17. if (number < 26) {
  18. return String.fromCharCode(65 + number);
  19. }
  20. if (number < 52) {
  21. return String.fromCharCode(97 + (number - 26));
  22. }
  23. if (number < 62) {
  24. return String.fromCharCode(48 + (number - 52));
  25. }
  26. if (number === 62) {
  27. return '+';
  28. }
  29. if (number === 63) {
  30. return '/';
  31. }
  32. throw new TypeError('Tried to encode large digit ' + number + ' in base64.');
  33. }
  34. var ParseFile = function () {
  35. function ParseFile(name, data, type, metadata, tags) {
  36. (0, _classCallCheck2.default)(this, ParseFile);
  37. var specifiedType = type || '';
  38. this._name = name;
  39. this._metadata = metadata || {};
  40. this._tags = tags || {};
  41. if (data !== undefined) {
  42. if (Array.isArray(data)) {
  43. this._data = ParseFile.encodeBase64(data);
  44. this._source = {
  45. format: 'base64',
  46. base64: this._data,
  47. type: specifiedType
  48. };
  49. } else if (typeof Blob !== 'undefined' && data instanceof Blob) {
  50. this._source = {
  51. format: 'file',
  52. file: data,
  53. type: specifiedType
  54. };
  55. } else if (data && typeof data.uri === 'string' && data.uri !== undefined) {
  56. this._source = {
  57. format: 'uri',
  58. uri: data.uri,
  59. type: specifiedType
  60. };
  61. } else if (data && typeof data.base64 === 'string') {
  62. var base64 = data.base64.split(',').slice(-1)[0];
  63. var dataType = specifiedType || data.base64.split(';').slice(0, 1)[0].split(':').slice(1, 2)[0] || 'text/plain';
  64. this._data = base64;
  65. this._source = {
  66. format: 'base64',
  67. base64: base64,
  68. type: dataType
  69. };
  70. } else {
  71. throw new TypeError('Cannot create a Parse.File with that data.');
  72. }
  73. }
  74. }
  75. (0, _createClass2.default)(ParseFile, [{
  76. key: "getData",
  77. value: function () {
  78. var _getData = (0, _asyncToGenerator2.default)(function* () {
  79. var _this = this;
  80. if (this._data) {
  81. return this._data;
  82. }
  83. if (!this._url) {
  84. throw new Error('Cannot retrieve data for unsaved ParseFile.');
  85. }
  86. var controller = _CoreManager.default.getFileController();
  87. var result = yield controller.download(this._url, {
  88. requestTask: function (task) {
  89. return _this._requestTask = task;
  90. }
  91. });
  92. this._data = result.base64;
  93. return this._data;
  94. });
  95. function getData() {
  96. return _getData.apply(this, arguments);
  97. }
  98. return getData;
  99. }()
  100. }, {
  101. key: "name",
  102. value: function () {
  103. return this._name;
  104. }
  105. }, {
  106. key: "url",
  107. value: function (options) {
  108. options = options || {};
  109. if (!this._url) {
  110. return;
  111. }
  112. if (options.forceSecure) {
  113. return this._url.replace(/^http:\/\//i, 'https://');
  114. } else {
  115. return this._url;
  116. }
  117. }
  118. }, {
  119. key: "metadata",
  120. value: function () {
  121. return this._metadata;
  122. }
  123. }, {
  124. key: "tags",
  125. value: function () {
  126. return this._tags;
  127. }
  128. }, {
  129. key: "save",
  130. value: function (options) {
  131. var _this2 = this;
  132. options = options || {};
  133. options.requestTask = function (task) {
  134. return _this2._requestTask = task;
  135. };
  136. options.metadata = this._metadata;
  137. options.tags = this._tags;
  138. var controller = _CoreManager.default.getFileController();
  139. if (!this._previousSave) {
  140. if (this._source.format === 'file') {
  141. this._previousSave = controller.saveFile(this._name, this._source, options).then(function (res) {
  142. _this2._name = res.name;
  143. _this2._url = res.url;
  144. _this2._data = null;
  145. _this2._requestTask = null;
  146. return _this2;
  147. });
  148. } else if (this._source.format === 'uri') {
  149. this._previousSave = controller.download(this._source.uri, options).then(function (result) {
  150. if (!(result && result.base64)) {
  151. return {};
  152. }
  153. var newSource = {
  154. format: 'base64',
  155. base64: result.base64,
  156. type: result.contentType
  157. };
  158. _this2._data = result.base64;
  159. _this2._requestTask = null;
  160. return controller.saveBase64(_this2._name, newSource, options);
  161. }).then(function (res) {
  162. _this2._name = res.name;
  163. _this2._url = res.url;
  164. _this2._requestTask = null;
  165. return _this2;
  166. });
  167. } else {
  168. this._previousSave = controller.saveBase64(this._name, this._source, options).then(function (res) {
  169. _this2._name = res.name;
  170. _this2._url = res.url;
  171. _this2._requestTask = null;
  172. return _this2;
  173. });
  174. }
  175. }
  176. if (this._previousSave) {
  177. return this._previousSave;
  178. }
  179. }
  180. }, {
  181. key: "cancel",
  182. value: function () {
  183. if (this._requestTask && typeof this._requestTask.abort === 'function') {
  184. this._requestTask._aborted = true;
  185. this._requestTask.abort();
  186. }
  187. this._requestTask = null;
  188. }
  189. }, {
  190. key: "destroy",
  191. value: function () {
  192. var _this3 = this;
  193. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  194. if (!this._name) {
  195. throw new ParseError(ParseError.FILE_DELETE_UNNAMED_ERROR, 'Cannot delete an unnamed file.');
  196. }
  197. var destroyOptions = {
  198. useMasterKey: true
  199. };
  200. if (options.hasOwnProperty('useMasterKey')) {
  201. destroyOptions.useMasterKey = options.useMasterKey;
  202. }
  203. var controller = _CoreManager.default.getFileController();
  204. return controller.deleteFile(this._name, destroyOptions).then(function () {
  205. _this3._data = null;
  206. _this3._requestTask = null;
  207. return _this3;
  208. });
  209. }
  210. }, {
  211. key: "toJSON",
  212. value: function () {
  213. return {
  214. __type: 'File',
  215. name: this._name,
  216. url: this._url
  217. };
  218. }
  219. }, {
  220. key: "equals",
  221. value: function (other) {
  222. if (this === other) {
  223. return true;
  224. }
  225. return other instanceof ParseFile && this.name() === other.name() && this.url() === other.url() && typeof this.url() !== 'undefined';
  226. }
  227. }, {
  228. key: "setMetadata",
  229. value: function (metadata) {
  230. var _this4 = this;
  231. if (metadata && typeof metadata === 'object') {
  232. Object.keys(metadata).forEach(function (key) {
  233. _this4.addMetadata(key, metadata[key]);
  234. });
  235. }
  236. }
  237. }, {
  238. key: "addMetadata",
  239. value: function (key, value) {
  240. if (typeof key === 'string') {
  241. this._metadata[key] = value;
  242. }
  243. }
  244. }, {
  245. key: "setTags",
  246. value: function (tags) {
  247. var _this5 = this;
  248. if (tags && typeof tags === 'object') {
  249. Object.keys(tags).forEach(function (key) {
  250. _this5.addTag(key, tags[key]);
  251. });
  252. }
  253. }
  254. }, {
  255. key: "addTag",
  256. value: function (key, value) {
  257. if (typeof key === 'string') {
  258. this._tags[key] = value;
  259. }
  260. }
  261. }], [{
  262. key: "fromJSON",
  263. value: function (obj) {
  264. if (obj.__type !== 'File') {
  265. throw new TypeError('JSON object does not represent a ParseFile');
  266. }
  267. var file = new ParseFile(obj.name);
  268. file._url = obj.url;
  269. return file;
  270. }
  271. }, {
  272. key: "encodeBase64",
  273. value: function (bytes) {
  274. var chunks = [];
  275. chunks.length = Math.ceil(bytes.length / 3);
  276. for (var i = 0; i < chunks.length; i++) {
  277. var b1 = bytes[i * 3];
  278. var b2 = bytes[i * 3 + 1] || 0;
  279. var b3 = bytes[i * 3 + 2] || 0;
  280. var has2 = i * 3 + 1 < bytes.length;
  281. var has3 = i * 3 + 2 < bytes.length;
  282. chunks[i] = [b64Digit(b1 >> 2 & 0x3f), b64Digit(b1 << 4 & 0x30 | b2 >> 4 & 0x0f), has2 ? b64Digit(b2 << 2 & 0x3c | b3 >> 6 & 0x03) : '=', has3 ? b64Digit(b3 & 0x3f) : '='].join('');
  283. }
  284. return chunks.join('');
  285. }
  286. }]);
  287. return ParseFile;
  288. }();
  289. var DefaultController = {
  290. saveFile: function () {
  291. var _saveFile = (0, _asyncToGenerator2.default)(function* (name, source, options) {
  292. if (source.format !== 'file') {
  293. throw new Error('saveFile can only be used with File-type sources.');
  294. }
  295. var base64Data = yield new Promise(function (res, rej) {
  296. var reader = new FileReader();
  297. reader.onload = function () {
  298. return res(reader.result);
  299. };
  300. reader.onerror = function (error) {
  301. return rej(error);
  302. };
  303. reader.readAsDataURL(source.file);
  304. });
  305. var _base64Data$split = base64Data.split(','),
  306. _base64Data$split2 = (0, _slicedToArray2.default)(_base64Data$split, 2),
  307. first = _base64Data$split2[0],
  308. second = _base64Data$split2[1];
  309. var data = second ? second : first;
  310. var newSource = {
  311. format: 'base64',
  312. base64: data,
  313. type: source.type || (source.file ? source.file.type : null)
  314. };
  315. return yield DefaultController.saveBase64(name, newSource, options);
  316. });
  317. function saveFile() {
  318. return _saveFile.apply(this, arguments);
  319. }
  320. return saveFile;
  321. }(),
  322. saveBase64: function (name, source, options) {
  323. if (source.format !== 'base64') {
  324. throw new Error('saveBase64 can only be used with Base64-type sources.');
  325. }
  326. var data = {
  327. base64: source.base64,
  328. fileData: {
  329. metadata: Object.assign({}, options.metadata),
  330. tags: Object.assign({}, options.tags)
  331. }
  332. };
  333. delete options.metadata;
  334. delete options.tags;
  335. if (source.type) {
  336. data._ContentType = source.type;
  337. }
  338. return _CoreManager.default.getRESTController().request('POST', 'files/' + name, data, options);
  339. },
  340. download: function (uri, options) {
  341. if (XHR) {
  342. return this.downloadAjax(uri, options);
  343. } else {
  344. return Promise.reject('Cannot make a request: No definition of XMLHttpRequest was found.');
  345. }
  346. },
  347. downloadAjax: function (uri, options) {
  348. return new Promise(function (resolve, reject) {
  349. var xhr = new XHR();
  350. xhr.open('GET', uri, true);
  351. xhr.responseType = 'arraybuffer';
  352. xhr.onerror = function (e) {
  353. reject(e);
  354. };
  355. xhr.onreadystatechange = function () {
  356. if (xhr.readyState !== xhr.DONE) {
  357. return;
  358. }
  359. if (!this.response) {
  360. return resolve({});
  361. }
  362. var bytes = new Uint8Array(this.response);
  363. resolve({
  364. base64: ParseFile.encodeBase64(bytes),
  365. contentType: xhr.getResponseHeader('content-type')
  366. });
  367. };
  368. options.requestTask(xhr);
  369. xhr.send();
  370. });
  371. },
  372. deleteFile: function (name, options) {
  373. var headers = {
  374. 'X-Parse-Application-ID': _CoreManager.default.get('APPLICATION_ID')
  375. };
  376. if (options.useMasterKey) {
  377. headers['X-Parse-Master-Key'] = _CoreManager.default.get('MASTER_KEY');
  378. }
  379. var url = _CoreManager.default.get('SERVER_URL');
  380. if (url[url.length - 1] !== '/') {
  381. url += '/';
  382. }
  383. url += 'files/' + name;
  384. return _CoreManager.default.getRESTController().ajax('DELETE', url, '', headers).catch(function (response) {
  385. if (!response || response === 'SyntaxError: Unexpected end of JSON input') {
  386. return Promise.resolve();
  387. } else {
  388. return _CoreManager.default.getRESTController().handleError(response);
  389. }
  390. });
  391. },
  392. _setXHR: function (xhr) {
  393. XHR = xhr;
  394. },
  395. _getXHR: function () {
  396. return XHR;
  397. }
  398. };
  399. _CoreManager.default.setFileController(DefaultController);
  400. var _default = ParseFile;
  401. exports.default = _default;
  402. exports.b64Digit = b64Digit;