request.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. function getError(option, xhr) {
  2. var msg = "cannot ".concat(option.method, " ").concat(option.action, " ").concat(xhr.status, "'");
  3. var err = new Error(msg);
  4. err.status = xhr.status;
  5. err.method = option.method;
  6. err.url = option.action;
  7. return err;
  8. }
  9. function getBody(xhr) {
  10. var text = xhr.responseText || xhr.response;
  11. if (!text) {
  12. return text;
  13. }
  14. try {
  15. return JSON.parse(text);
  16. } catch (e) {
  17. return text;
  18. }
  19. }
  20. export default function upload(option) {
  21. // eslint-disable-next-line no-undef
  22. var xhr = new XMLHttpRequest();
  23. if (option.onProgress && xhr.upload) {
  24. xhr.upload.onprogress = function progress(e) {
  25. if (e.total > 0) {
  26. e.percent = e.loaded / e.total * 100;
  27. }
  28. option.onProgress(e);
  29. };
  30. }
  31. // eslint-disable-next-line no-undef
  32. var formData = new FormData();
  33. if (option.data) {
  34. Object.keys(option.data).forEach(function (key) {
  35. var value = option.data[key];
  36. // support key-value array data
  37. if (Array.isArray(value)) {
  38. value.forEach(function (item) {
  39. // { list: [ 11, 22 ] }
  40. // formData.append('list[]', 11);
  41. formData.append("".concat(key, "[]"), item);
  42. });
  43. return;
  44. }
  45. formData.append(key, value);
  46. });
  47. }
  48. // eslint-disable-next-line no-undef
  49. if (option.file instanceof Blob) {
  50. formData.append(option.filename, option.file, option.file.name);
  51. } else {
  52. formData.append(option.filename, option.file);
  53. }
  54. xhr.onerror = function error(e) {
  55. option.onError(e);
  56. };
  57. xhr.onload = function onload() {
  58. // allow success when 2xx status
  59. // see https://github.com/react-component/upload/issues/34
  60. if (xhr.status < 200 || xhr.status >= 300) {
  61. return option.onError(getError(option, xhr), getBody(xhr));
  62. }
  63. return option.onSuccess(getBody(xhr), xhr);
  64. };
  65. xhr.open(option.method, option.action, true);
  66. // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179
  67. if (option.withCredentials && 'withCredentials' in xhr) {
  68. xhr.withCredentials = true;
  69. }
  70. var headers = option.headers || {};
  71. // when set headers['X-Requested-With'] = null , can close default XHR header
  72. // see https://github.com/react-component/upload/issues/33
  73. if (headers['X-Requested-With'] !== null) {
  74. xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
  75. }
  76. Object.keys(headers).forEach(function (h) {
  77. if (headers[h] !== null) {
  78. xhr.setRequestHeader(h, headers[h]);
  79. }
  80. });
  81. xhr.send(formData);
  82. return {
  83. abort: function abort() {
  84. xhr.abort();
  85. }
  86. };
  87. }