AjaxUploader.js 13 KB

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