toFormData.js 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. 'use strict';
  2. var utils = require('../utils');
  3. /**
  4. * Convert a data object to FormData
  5. * @param {Object} obj
  6. * @param {?Object} [formData]
  7. * @returns {Object}
  8. **/
  9. function toFormData(obj, formData) {
  10. // eslint-disable-next-line no-param-reassign
  11. formData = formData || new FormData();
  12. var stack = [];
  13. function convertValue(value) {
  14. if (value === null) return '';
  15. if (utils.isDate(value)) {
  16. return value.toISOString();
  17. }
  18. if (utils.isArrayBuffer(value) || utils.isTypedArray(value)) {
  19. return typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value);
  20. }
  21. return value;
  22. }
  23. function build(data, parentKey) {
  24. if (utils.isPlainObject(data) || utils.isArray(data)) {
  25. if (stack.indexOf(data) !== -1) {
  26. throw Error('Circular reference detected in ' + parentKey);
  27. }
  28. stack.push(data);
  29. utils.forEach(data, function each(value, key) {
  30. if (utils.isUndefined(value)) return;
  31. var fullKey = parentKey ? parentKey + '.' + key : key;
  32. var arr;
  33. if (value && !parentKey && typeof value === 'object') {
  34. if (utils.endsWith(key, '{}')) {
  35. // eslint-disable-next-line no-param-reassign
  36. value = JSON.stringify(value);
  37. } else if (utils.endsWith(key, '[]') && (arr = utils.toArray(value))) {
  38. // eslint-disable-next-line func-names
  39. arr.forEach(function(el) {
  40. !utils.isUndefined(el) && formData.append(fullKey, convertValue(el));
  41. });
  42. return;
  43. }
  44. }
  45. build(value, fullKey);
  46. });
  47. stack.pop();
  48. } else {
  49. formData.append(parentKey, convertValue(data));
  50. }
  51. }
  52. build(obj);
  53. return formData;
  54. }
  55. module.exports = toFormData;