AjaxUploader.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.default = void 0;
  7. var _vue = require("vue");
  8. var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
  9. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
  10. var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
  11. var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
  12. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  13. var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
  14. var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
  15. var _request = _interopRequireDefault(require("./request"));
  16. var _uid2 = _interopRequireDefault(require("./uid"));
  17. var _attrAccept = _interopRequireDefault(require("./attr-accept"));
  18. var _traverseFileTree = _interopRequireDefault(require("./traverseFileTree"));
  19. var _interface = require("./interface");
  20. var _pickAttrs = _interopRequireDefault(require("../_util/pickAttrs"));
  21. var _partition = _interopRequireDefault(require("lodash/partition"));
  22. var _excluded = ["componentTag", "prefixCls", "disabled", "id", "multiple", "accept", "capture", "directory", "openFileDialogOnClick", "onMouseenter", "onMouseleave"];
  23. var _default2 = (0, _vue.defineComponent)({
  24. compatConfig: {
  25. MODE: 3
  26. },
  27. name: 'AjaxUploader',
  28. inheritAttrs: false,
  29. props: (0, _interface.uploadProps)(),
  30. setup: function setup(props, _ref) {
  31. var slots = _ref.slots,
  32. attrs = _ref.attrs,
  33. expose = _ref.expose;
  34. var uid = (0, _vue.ref)((0, _uid2.default)());
  35. var reqs = {};
  36. var fileInput = (0, _vue.ref)();
  37. var isMounted = false;
  38. /**
  39. * Process file before upload. When all the file is ready, we start upload.
  40. */
  41. var processFile = /*#__PURE__*/function () {
  42. var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(file, fileList) {
  43. var beforeUpload, transformedFile, action, mergedAction, data, mergedData, parsedData, parsedFile, mergedParsedFile;
  44. return _regenerator.default.wrap(function _callee$(_context) {
  45. while (1) {
  46. switch (_context.prev = _context.next) {
  47. case 0:
  48. beforeUpload = props.beforeUpload;
  49. transformedFile = file;
  50. if (!beforeUpload) {
  51. _context.next = 14;
  52. break;
  53. }
  54. _context.prev = 3;
  55. _context.next = 6;
  56. return beforeUpload(file, fileList);
  57. case 6:
  58. transformedFile = _context.sent;
  59. _context.next = 12;
  60. break;
  61. case 9:
  62. _context.prev = 9;
  63. _context.t0 = _context["catch"](3);
  64. // Rejection will also trade as false
  65. transformedFile = false;
  66. case 12:
  67. if (!(transformedFile === false)) {
  68. _context.next = 14;
  69. break;
  70. }
  71. return _context.abrupt("return", {
  72. origin: file,
  73. parsedFile: null,
  74. action: null,
  75. data: null
  76. });
  77. case 14:
  78. // Get latest action
  79. action = props.action;
  80. if (!(typeof action === 'function')) {
  81. _context.next = 21;
  82. break;
  83. }
  84. _context.next = 18;
  85. return action(file);
  86. case 18:
  87. mergedAction = _context.sent;
  88. _context.next = 22;
  89. break;
  90. case 21:
  91. mergedAction = action;
  92. case 22:
  93. // Get latest data
  94. data = props.data;
  95. if (!(typeof data === 'function')) {
  96. _context.next = 29;
  97. break;
  98. }
  99. _context.next = 26;
  100. return data(file);
  101. case 26:
  102. mergedData = _context.sent;
  103. _context.next = 30;
  104. break;
  105. case 29:
  106. mergedData = data;
  107. case 30:
  108. parsedData =
  109. // string type is from legacy `transformFile`.
  110. // Not sure if this will work since no related test case works with it
  111. ((0, _typeof2.default)(transformedFile) === 'object' || typeof transformedFile === 'string') && transformedFile ? transformedFile : file;
  112. if (parsedData instanceof File) {
  113. parsedFile = parsedData;
  114. } else {
  115. parsedFile = new File([parsedData], file.name, {
  116. type: file.type
  117. });
  118. }
  119. mergedParsedFile = parsedFile;
  120. mergedParsedFile.uid = file.uid;
  121. return _context.abrupt("return", {
  122. origin: file,
  123. data: mergedData,
  124. parsedFile: mergedParsedFile,
  125. action: mergedAction
  126. });
  127. case 35:
  128. case "end":
  129. return _context.stop();
  130. }
  131. }
  132. }, _callee, null, [[3, 9]]);
  133. }));
  134. return function processFile(_x, _x2) {
  135. return _ref2.apply(this, arguments);
  136. };
  137. }();
  138. var post = function post(_ref3) {
  139. var data = _ref3.data,
  140. origin = _ref3.origin,
  141. action = _ref3.action,
  142. parsedFile = _ref3.parsedFile;
  143. if (!isMounted) {
  144. return;
  145. }
  146. var onStart = props.onStart,
  147. customRequest = props.customRequest,
  148. name = props.name,
  149. headers = props.headers,
  150. withCredentials = props.withCredentials,
  151. method = props.method;
  152. var uid = origin.uid;
  153. var request = customRequest || _request.default;
  154. var requestOption = {
  155. action: action,
  156. filename: name,
  157. data: data,
  158. file: parsedFile,
  159. headers: headers,
  160. withCredentials: withCredentials,
  161. method: method || 'post',
  162. onProgress: function onProgress(e) {
  163. var onProgress = props.onProgress;
  164. onProgress === null || onProgress === void 0 ? void 0 : onProgress(e, parsedFile);
  165. },
  166. onSuccess: function onSuccess(ret, xhr) {
  167. var onSuccess = props.onSuccess;
  168. onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(ret, parsedFile, xhr);
  169. delete reqs[uid];
  170. },
  171. onError: function onError(err, ret) {
  172. var onError = props.onError;
  173. onError === null || onError === void 0 ? void 0 : onError(err, ret, parsedFile);
  174. delete reqs[uid];
  175. }
  176. };
  177. onStart(origin);
  178. reqs[uid] = request(requestOption);
  179. };
  180. var reset = function reset() {
  181. uid.value = (0, _uid2.default)();
  182. };
  183. var abort = function abort(file) {
  184. if (file) {
  185. var _uid = file.uid ? file.uid : file;
  186. if (reqs[_uid] && reqs[_uid].abort) {
  187. reqs[_uid].abort();
  188. }
  189. delete reqs[_uid];
  190. } else {
  191. Object.keys(reqs).forEach(function (uid) {
  192. if (reqs[uid] && reqs[uid].abort) {
  193. reqs[uid].abort();
  194. }
  195. delete reqs[uid];
  196. });
  197. }
  198. };
  199. (0, _vue.onMounted)(function () {
  200. isMounted = true;
  201. });
  202. (0, _vue.onBeforeUnmount)(function () {
  203. isMounted = false;
  204. abort();
  205. });
  206. var uploadFiles = function uploadFiles(files) {
  207. var originFiles = (0, _toConsumableArray2.default)(files);
  208. var postFiles = originFiles.map(function (file) {
  209. // eslint-disable-next-line no-param-reassign
  210. file.uid = (0, _uid2.default)();
  211. return processFile(file, originFiles);
  212. });
  213. // Batch upload files
  214. Promise.all(postFiles).then(function (fileList) {
  215. var onBatchStart = props.onBatchStart;
  216. onBatchStart === null || onBatchStart === void 0 ? void 0 : onBatchStart(fileList.map(function (_ref4) {
  217. var origin = _ref4.origin,
  218. parsedFile = _ref4.parsedFile;
  219. return {
  220. file: origin,
  221. parsedFile: parsedFile
  222. };
  223. }));
  224. fileList.filter(function (file) {
  225. return file.parsedFile !== null;
  226. }).forEach(function (file) {
  227. post(file);
  228. });
  229. });
  230. };
  231. var onChange = function onChange(e) {
  232. var accept = props.accept,
  233. directory = props.directory;
  234. var files = e.target.files;
  235. var acceptedFiles = (0, _toConsumableArray2.default)(files).filter(function (file) {
  236. return !directory || (0, _attrAccept.default)(file, accept);
  237. });
  238. uploadFiles(acceptedFiles);
  239. reset();
  240. };
  241. var onClick = function onClick(e) {
  242. var el = fileInput.value;
  243. if (!el) {
  244. return;
  245. }
  246. var onClick = props.onClick;
  247. // TODO
  248. // if (children && (children as any).type === 'button') {
  249. // const parent = el.parentNode as HTMLInputElement;
  250. // parent.focus();
  251. // parent.querySelector('button').blur();
  252. // }
  253. el.click();
  254. if (onClick) {
  255. onClick(e);
  256. }
  257. };
  258. var onKeyDown = function onKeyDown(e) {
  259. if (e.key === 'Enter') {
  260. onClick(e);
  261. }
  262. };
  263. var onFileDrop = function onFileDrop(e) {
  264. var multiple = props.multiple;
  265. e.preventDefault();
  266. if (e.type === 'dragover') {
  267. return;
  268. }
  269. if (props.directory) {
  270. (0, _traverseFileTree.default)(Array.prototype.slice.call(e.dataTransfer.items), uploadFiles, function (_file) {
  271. return (0, _attrAccept.default)(_file, props.accept);
  272. });
  273. } else {
  274. var files = (0, _partition.default)(Array.prototype.slice.call(e.dataTransfer.files), function (file) {
  275. return (0, _attrAccept.default)(file, props.accept);
  276. });
  277. var successFiles = files[0];
  278. var errorFiles = files[1];
  279. if (multiple === false) {
  280. successFiles = successFiles.slice(0, 1);
  281. }
  282. uploadFiles(successFiles);
  283. if (errorFiles.length && props.onReject) props.onReject(errorFiles);
  284. }
  285. };
  286. expose({
  287. abort: abort
  288. });
  289. return function () {
  290. var _cls, _slots$default;
  291. var Tag = props.componentTag,
  292. prefixCls = props.prefixCls,
  293. disabled = props.disabled,
  294. id = props.id,
  295. multiple = props.multiple,
  296. accept = props.accept,
  297. capture = props.capture,
  298. directory = props.directory,
  299. openFileDialogOnClick = props.openFileDialogOnClick,
  300. onMouseenter = props.onMouseenter,
  301. onMouseleave = props.onMouseleave,
  302. otherProps = (0, _objectWithoutProperties2.default)(props, _excluded);
  303. var cls = (_cls = {}, (0, _defineProperty2.default)(_cls, prefixCls, true), (0, _defineProperty2.default)(_cls, "".concat(prefixCls, "-disabled"), disabled), (0, _defineProperty2.default)(_cls, attrs.class, !!attrs.class), _cls);
  304. // because input don't have directory/webkitdirectory type declaration
  305. var dirProps = directory ? {
  306. directory: 'directory',
  307. webkitdirectory: 'webkitdirectory'
  308. } : {};
  309. var events = disabled ? {} : {
  310. onClick: openFileDialogOnClick ? onClick : function () {},
  311. onKeydown: openFileDialogOnClick ? onKeyDown : function () {},
  312. onMouseenter: onMouseenter,
  313. onMouseleave: onMouseleave,
  314. onDrop: onFileDrop,
  315. onDragover: onFileDrop,
  316. tabindex: '0'
  317. };
  318. return (0, _vue.createVNode)(Tag, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, events), {}, {
  319. "class": cls,
  320. "role": "button",
  321. "style": attrs.style
  322. }), {
  323. default: function _default() {
  324. return [(0, _vue.createVNode)("input", (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, (0, _pickAttrs.default)(otherProps, {
  325. aria: true,
  326. data: true
  327. })), {}, {
  328. "id": id,
  329. "type": "file",
  330. "ref": fileInput,
  331. "onClick": function onClick(e) {
  332. return e.stopPropagation();
  333. },
  334. "key": uid.value,
  335. "style": {
  336. display: 'none'
  337. },
  338. "accept": accept
  339. }, dirProps), {}, {
  340. "multiple": multiple,
  341. "onChange": onChange
  342. }, capture != null ? {
  343. capture: capture
  344. } : {}), null), (_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots)];
  345. }
  346. });
  347. };
  348. }
  349. });
  350. exports.default = _default2;