ParseFile.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. "use strict";
  2. var _Object$keys2 = require("@babel/runtime-corejs3/core-js-stable/object/keys");
  3. var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols");
  4. var _filterInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/filter");
  5. var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor");
  6. var _forEachInstanceProperty2 = require("@babel/runtime-corejs3/core-js-stable/instance/for-each");
  7. var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors");
  8. var _Object$defineProperties = require("@babel/runtime-corejs3/core-js-stable/object/define-properties");
  9. var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property");
  10. var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
  11. _Object$defineProperty(exports, "__esModule", {
  12. value: true
  13. });
  14. exports.default = void 0;
  15. var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs3/regenerator"));
  16. var _isArray = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/array/is-array"));
  17. var _indexOf = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/index-of"));
  18. var _slice = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/slice"));
  19. var _forEach = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/for-each"));
  20. var _keys = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/object/keys"));
  21. var _typeof2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/typeof"));
  22. var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/asyncToGenerator"));
  23. var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/classCallCheck"));
  24. var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/createClass"));
  25. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty"));
  26. var _CoreManager = _interopRequireDefault(require("./CoreManager"));
  27. var _ParseFileEncode = require("./ParseFileEncode");
  28. function ownKeys(object, enumerableOnly) {
  29. var keys = _Object$keys2(object);
  30. if (_Object$getOwnPropertySymbols) {
  31. var symbols = _Object$getOwnPropertySymbols(object);
  32. enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) {
  33. return _Object$getOwnPropertyDescriptor(object, sym).enumerable;
  34. })), keys.push.apply(keys, symbols);
  35. }
  36. return keys;
  37. }
  38. function _objectSpread(target) {
  39. for (var i = 1; i < arguments.length; i++) {
  40. var _context4, _context5;
  41. var source = null != arguments[i] ? arguments[i] : {};
  42. i % 2 ? _forEachInstanceProperty2(_context4 = ownKeys(Object(source), !0)).call(_context4, function (key) {
  43. (0, _defineProperty2.default)(target, key, source[key]);
  44. }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty2(_context5 = ownKeys(Object(source))).call(_context5, function (key) {
  45. _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key));
  46. });
  47. }
  48. return target;
  49. }
  50. var ParseError = require('./ParseError').default;
  51. /*:: type Base64 = { base64: string };*/
  52. /*:: type Uri = { uri: string };*/
  53. /*:: type FileData = Array<number> | Base64 | Blob | Uri;*/
  54. /*:: export type FileSource =
  55. | {
  56. format: 'file',
  57. file: Blob,
  58. type: string,
  59. }
  60. | {
  61. format: 'base64',
  62. base64: string,
  63. type: string,
  64. }
  65. | {
  66. format: 'uri',
  67. uri: string,
  68. type: string,
  69. };*/
  70. var dataUriRegexp = /^data:([a-zA-Z]+\/[-a-zA-Z0-9+.]+)(;charset=[a-zA-Z0-9\-/]*)?;base64,/;
  71. /**
  72. * A Parse.File is a local representation of a file that is saved to the Parse
  73. * cloud.
  74. *
  75. * @alias Parse.File
  76. */
  77. var ParseFile = /*#__PURE__*/function () {
  78. /**
  79. * @param name {String} The file's name. This will be prefixed by a unique
  80. * value once the file has finished saving. The file name must begin with
  81. * an alphanumeric character, and consist of alphanumeric characters,
  82. * periods, spaces, underscores, or dashes.
  83. * @param data {Array} The data for the file, as either:
  84. * 1. an Array of byte value Numbers, or
  85. * 2. an Object like { base64: "..." } with a base64-encoded String.
  86. * 3. an Object like { uri: "..." } with a uri String.
  87. * 4. a File object selected with a file upload control. (3) only works
  88. * in Firefox 3.6+, Safari 6.0.2+, Chrome 7+, and IE 10+.
  89. * For example:
  90. * <pre>
  91. * var fileUploadControl = $("#profilePhotoFileUpload")[0];
  92. * if (fileUploadControl.files.length > 0) {
  93. * var file = fileUploadControl.files[0];
  94. * var name = "photo.jpg";
  95. * var parseFile = new Parse.File(name, file);
  96. * parseFile.save().then(function() {
  97. * // The file has been saved to Parse.
  98. * }, function(error) {
  99. * // The file either could not be read, or could not be saved to Parse.
  100. * });
  101. * }</pre>
  102. * @param type {String} Optional Content-Type header to use for the file. If
  103. * this is omitted, the content type will be inferred from the name's
  104. * extension.
  105. * @param metadata {Object} Optional key value pairs to be stored with file object
  106. * @param tags {Object} Optional key value pairs to be stored with file object
  107. */
  108. function ParseFile(name
  109. /*: string*/
  110. , data
  111. /*:: ?: FileData*/
  112. , type
  113. /*:: ?: string*/
  114. , metadata
  115. /*:: ?: Object*/
  116. , tags
  117. /*:: ?: Object*/
  118. ) {
  119. (0, _classCallCheck2.default)(this, ParseFile);
  120. (0, _defineProperty2.default)(this, "_name", void 0);
  121. (0, _defineProperty2.default)(this, "_url", void 0);
  122. (0, _defineProperty2.default)(this, "_hash", void 0);
  123. (0, _defineProperty2.default)(this, "_ipfs", void 0);
  124. (0, _defineProperty2.default)(this, "_source", void 0);
  125. (0, _defineProperty2.default)(this, "_previousSave", void 0);
  126. (0, _defineProperty2.default)(this, "_data", void 0);
  127. (0, _defineProperty2.default)(this, "_requestTask", void 0);
  128. (0, _defineProperty2.default)(this, "_metadata", void 0);
  129. (0, _defineProperty2.default)(this, "_tags", void 0);
  130. var specifiedType = type || '';
  131. this._name = name;
  132. this._metadata = metadata || {};
  133. this._tags = tags || {};
  134. if (data !== undefined) {
  135. if ((0, _isArray.default)(data)) {
  136. this._data = ParseFile.encodeBase64(data);
  137. this._source = {
  138. format: 'base64',
  139. base64: this._data,
  140. type: specifiedType
  141. };
  142. } else if (typeof Blob !== 'undefined' && data instanceof Blob) {
  143. this._source = {
  144. format: 'file',
  145. file: data,
  146. type: specifiedType
  147. };
  148. } else if (data && typeof data.uri === 'string' && data.uri !== undefined) {
  149. this._source = {
  150. format: 'uri',
  151. uri: data.uri,
  152. type: specifiedType
  153. };
  154. } else if (data && typeof data.base64 === 'string') {
  155. var base64 = data.base64;
  156. var commaIndex = (0, _indexOf.default)(base64).call(base64, ',');
  157. if (commaIndex !== -1) {
  158. var matches = dataUriRegexp.exec((0, _slice.default)(base64).call(base64, 0, commaIndex + 1)); // if data URI with type and charset, there will be 4 matches.
  159. this._data = (0, _slice.default)(base64).call(base64, commaIndex + 1);
  160. this._source = {
  161. format: 'base64',
  162. base64: this._data,
  163. type: matches[1]
  164. };
  165. } else {
  166. this._data = base64;
  167. this._source = {
  168. format: 'base64',
  169. base64: base64,
  170. type: specifiedType
  171. };
  172. }
  173. } else {
  174. throw new TypeError('Cannot create a Parse.File with that data.');
  175. }
  176. }
  177. }
  178. /**
  179. * Return the data for the file, downloading it if not already present.
  180. * Data is present if initialized with Byte Array, Base64 or Saved with Uri.
  181. * Data is cleared if saved with File object selected with a file upload control
  182. *
  183. * @returns {Promise} Promise that is resolve with base64 data
  184. */
  185. (0, _createClass2.default)(ParseFile, [{
  186. key: "getData",
  187. value: function () {
  188. var _getData = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
  189. var _this = this;
  190. var options, controller, result;
  191. return _regenerator.default.wrap(function (_context) {
  192. while (1) {
  193. switch (_context.prev = _context.next) {
  194. case 0:
  195. if (!this._data) {
  196. _context.next = 2;
  197. break;
  198. }
  199. return _context.abrupt("return", this._data);
  200. case 2:
  201. if (this._url) {
  202. _context.next = 4;
  203. break;
  204. }
  205. throw new Error('Cannot retrieve data for unsaved ParseFile.');
  206. case 4:
  207. options = {
  208. requestTask: function (task) {
  209. return _this._requestTask = task;
  210. }
  211. };
  212. controller = _CoreManager.default.getFileController();
  213. _context.next = 8;
  214. return controller.download(this._url, options);
  215. case 8:
  216. result = _context.sent;
  217. this._data = result.base64;
  218. return _context.abrupt("return", this._data);
  219. case 11:
  220. case "end":
  221. return _context.stop();
  222. }
  223. }
  224. }, _callee, this);
  225. }));
  226. return function () {
  227. return _getData.apply(this, arguments);
  228. };
  229. }()
  230. /**
  231. * Gets the name of the file. Before save is called, this is the filename
  232. * given by the user. After save is called, that name gets prefixed with a
  233. * unique identifier.
  234. *
  235. * @returns {string}
  236. */
  237. }, {
  238. key: "name",
  239. value: function ()
  240. /*: string*/
  241. {
  242. return this._name;
  243. }
  244. /**
  245. * Gets the url of the file. It is only available after you save the file or
  246. * after you get the file from a Parse.Object.
  247. *
  248. * @param {object} options An object to specify url options
  249. * @returns {string}
  250. */
  251. }, {
  252. key: "url",
  253. value: function (options
  254. /*:: ?: { forceSecure?: boolean }*/
  255. )
  256. /*: ?string*/
  257. {
  258. options = options || {};
  259. if (!this._url) {
  260. return;
  261. }
  262. if (options.forceSecure) {
  263. return this._url.replace(/^http:\/\//i, 'https://');
  264. }
  265. return this._url;
  266. }
  267. }, {
  268. key: "ipfs",
  269. value: function () {
  270. return this._ipfs;
  271. }
  272. }, {
  273. key: "hash",
  274. value: function () {
  275. return this._hash;
  276. }
  277. /**
  278. * Gets the metadata of the file.
  279. *
  280. * @returns {object}
  281. */
  282. }, {
  283. key: "metadata",
  284. value: function ()
  285. /*: Object*/
  286. {
  287. return this._metadata;
  288. }
  289. /**
  290. * Gets the tags of the file.
  291. *
  292. * @returns {object}
  293. */
  294. }, {
  295. key: "tags",
  296. value: function ()
  297. /*: Object*/
  298. {
  299. return this._tags;
  300. }
  301. /**
  302. * Saves the file to the Parse cloud.
  303. *
  304. * @param {object} options
  305. * * Valid options are:<ul>
  306. * <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
  307. * be used for this request.
  308. * <li>sessionToken: A valid session token, used for making a request on
  309. * behalf of a specific user.
  310. * <li>progress: In Browser only, callback for upload progress. For example:
  311. * <pre>
  312. * let parseFile = new Parse.File(name, file);
  313. * parseFile.save({
  314. * progress: (progressValue, loaded, total, { type }) => {
  315. * if (type === "upload" && progressValue !== null) {
  316. * // Update the UI using progressValue
  317. * }
  318. * }
  319. * });
  320. * </pre>
  321. * </ul>
  322. * @returns {Promise} Promise that is resolved when the save finishes.
  323. */
  324. }, {
  325. key: "save",
  326. value: function (options
  327. /*:: ?: FullOptions*/
  328. ) {
  329. var _this2 = this;
  330. options = options || {};
  331. options.requestTask = function (task) {
  332. return _this2._requestTask = task;
  333. };
  334. options.metadata = this._metadata;
  335. options.tags = this._tags;
  336. var controller = _CoreManager.default.getFileController();
  337. if (!this._previousSave) {
  338. if (this._source.format === 'file') {
  339. this._previousSave = controller.saveFile(this._name, this._source, options).then(function (res) {
  340. _this2._name = res.name;
  341. _this2._url = res.url;
  342. _this2._hash = res.hash;
  343. _this2._ipfs = res.ipfs;
  344. _this2._data = null;
  345. _this2._requestTask = null;
  346. return _this2;
  347. });
  348. } else if (this._source.format === 'uri') {
  349. this._previousSave = controller.download(this._source.uri, options).then(function (result) {
  350. if (!(result && result.base64)) {
  351. return {};
  352. }
  353. var newSource = {
  354. format: 'base64',
  355. base64: result.base64,
  356. type: result.contentType
  357. };
  358. _this2._data = result.base64;
  359. _this2._requestTask = null;
  360. return controller.saveBase64(_this2._name, newSource, options);
  361. }).then(function (res) {
  362. _this2._name = res.name;
  363. _this2._url = res.url;
  364. _this2._hash = res.hash;
  365. _this2._ipfs = res.ipfs;
  366. _this2._requestTask = null;
  367. return _this2;
  368. });
  369. } else {
  370. this._previousSave = controller.saveBase64(this._name, this._source, options).then(function (res) {
  371. _this2._name = res.name;
  372. _this2._url = res.url;
  373. _this2._hash = res.hash;
  374. _this2._ipfs = res.ipfs;
  375. _this2._requestTask = null;
  376. return _this2;
  377. });
  378. }
  379. }
  380. if (this._previousSave) {
  381. return this._previousSave;
  382. }
  383. }
  384. }, {
  385. key: "saveIPFS",
  386. value: function (options
  387. /*:: ?: FullOptions*/
  388. ) {
  389. return this.save(_objectSpread(_objectSpread({}, options), {}, {
  390. ipfs: true
  391. }));
  392. }
  393. /**
  394. * Aborts the request if it has already been sent.
  395. */
  396. }, {
  397. key: "cancel",
  398. value: function () {
  399. if (this._requestTask && typeof this._requestTask.abort === 'function') {
  400. this._requestTask.abort();
  401. }
  402. this._requestTask = null;
  403. }
  404. /**
  405. * Deletes the file from the Parse cloud.
  406. * In Cloud Code and Node only with Master Key.
  407. *
  408. * @param {object} options
  409. * * Valid options are:<ul>
  410. * <li>useMasterKey: In Cloud Code and Node only, causes the Master Key to
  411. * be used for this request.
  412. * <pre>
  413. * @returns {Promise} Promise that is resolved when the delete finishes.
  414. */
  415. }, {
  416. key: "destroy",
  417. value: function () {
  418. var _this3 = this;
  419. var options
  420. /*:: ?: FullOptions*/
  421. = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  422. if (!this._name) {
  423. throw new ParseError(ParseError.FILE_DELETE_UNNAMED_ERROR, 'Cannot delete an unnamed file.');
  424. }
  425. var destroyOptions = {
  426. useMasterKey: true
  427. };
  428. if (options.hasOwnProperty('useMasterKey')) {
  429. destroyOptions.useMasterKey = options.useMasterKey;
  430. }
  431. var controller = _CoreManager.default.getFileController();
  432. return controller.deleteFile(this._name, destroyOptions).then(function () {
  433. _this3._data = null;
  434. _this3._requestTask = null;
  435. return _this3;
  436. });
  437. }
  438. }, {
  439. key: "toJSON",
  440. value: function ()
  441. /*: { name: ?string, url: ?string }*/
  442. {
  443. return {
  444. __type: 'File',
  445. name: this._name,
  446. url: this._url,
  447. ipfs: this._ipfs,
  448. hash: this._hash
  449. };
  450. }
  451. }, {
  452. key: "equals",
  453. value: function (other
  454. /*: mixed*/
  455. )
  456. /*: boolean*/
  457. {
  458. if (this === other) {
  459. return true;
  460. } // Unsaved Files are never equal, since they will be saved to different URLs
  461. return other instanceof ParseFile && this.name() === other.name() && this.url() === other.url() && typeof this.url() !== 'undefined';
  462. }
  463. /**
  464. * Sets metadata to be saved with file object. Overwrites existing metadata
  465. *
  466. * @param {object} metadata Key value pairs to be stored with file object
  467. */
  468. }, {
  469. key: "setMetadata",
  470. value: function (metadata
  471. /*: any*/
  472. ) {
  473. var _this4 = this;
  474. if (metadata && (0, _typeof2.default)(metadata) === 'object') {
  475. var _context2;
  476. (0, _forEach.default)(_context2 = (0, _keys.default)(metadata)).call(_context2, function (key) {
  477. _this4.addMetadata(key, metadata[key]);
  478. });
  479. }
  480. }
  481. /**
  482. * Sets metadata to be saved with file object. Adds to existing metadata.
  483. *
  484. * @param {string} key key to store the metadata
  485. * @param {*} value metadata
  486. */
  487. }, {
  488. key: "addMetadata",
  489. value: function (key
  490. /*: string*/
  491. , value
  492. /*: any*/
  493. ) {
  494. if (typeof key === 'string') {
  495. this._metadata[key] = value;
  496. }
  497. }
  498. /**
  499. * Sets tags to be saved with file object. Overwrites existing tags
  500. *
  501. * @param {object} tags Key value pairs to be stored with file object
  502. */
  503. }, {
  504. key: "setTags",
  505. value: function (tags
  506. /*: any*/
  507. ) {
  508. var _this5 = this;
  509. if (tags && (0, _typeof2.default)(tags) === 'object') {
  510. var _context3;
  511. (0, _forEach.default)(_context3 = (0, _keys.default)(tags)).call(_context3, function (key) {
  512. _this5.addTag(key, tags[key]);
  513. });
  514. }
  515. }
  516. /**
  517. * Sets tags to be saved with file object. Adds to existing tags.
  518. *
  519. * @param {string} key key to store tags
  520. * @param {*} value tag
  521. */
  522. }, {
  523. key: "addTag",
  524. value: function (key
  525. /*: string*/
  526. , value
  527. /*: string*/
  528. ) {
  529. if (typeof key === 'string') {
  530. this._tags[key] = value;
  531. }
  532. }
  533. }], [{
  534. key: "fromJSON",
  535. value: function (obj)
  536. /*: ParseFile*/
  537. {
  538. if (obj.__type !== 'File') {
  539. throw new TypeError('JSON object does not represent a ParseFile');
  540. }
  541. var file = new ParseFile(obj.name);
  542. file._url = obj.url;
  543. file._hash = obj.hash;
  544. file._ipfs = obj.ipfs;
  545. return file;
  546. }
  547. }, {
  548. key: "encodeBase64",
  549. value: function (bytes
  550. /*: Array<number>*/
  551. )
  552. /*: string*/
  553. {
  554. return (0, _ParseFileEncode.encodeBase64)(bytes);
  555. }
  556. }]);
  557. return ParseFile;
  558. }();
  559. _CoreManager.default.setFileController(require('./ParseFileController.default'));
  560. var _default = ParseFile;
  561. exports.default = _default;
  562. exports.b64Digit = _ParseFileEncode.b64Digit;