Last active
January 9, 2019 13:40
-
-
Save loilo/f6e0c8f89b8dd12ed0ea to your computer and use it in GitHub Desktop.
Serializes a form's elements into a ready-to-send POST body string
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const serializeMultipart = async form => { | |
const data = {} | |
const formdata = Array.from(form.querySelectorAll('input, select, textarea, button')).map(input => { | |
if (input.disabled) return false | |
switch (input.nodeName) { | |
case 'INPUT': | |
switch (input.type.toLowerCase()) { | |
case 'checkbox': | |
case 'radio': | |
if (input.selected) { | |
data[input.name] = input.value | |
} | |
break | |
case 'file': | |
data[input.name] = [] | |
const promises = Array.prototype.slice.call(input.files).map(file => { | |
return new Promise((resolve, reject) => { | |
const fr = new FileReader() | |
fr.onload = () => { | |
data[input.name].push({ | |
file: file, | |
binary: fr.result | |
}) | |
resolve() | |
} | |
fr.onerror = e => { | |
console.error(e) | |
reject(e) | |
} | |
fr.readAsBinaryString(file) | |
}) | |
}) | |
return Promise.all(promises) | |
default: | |
data[input.name] = input.value | |
} | |
break | |
case 'TEXTAREA': | |
data[input.name] = input.value | |
break | |
case 'SELECT': | |
if (input.type === 'select-one') { | |
data[input.name] = input.value | |
} else { | |
data[input.name] = [] | |
for (const option of input.childNodes) { | |
if (option.selected) { | |
data[input.name].push(option.value) | |
} | |
} | |
} | |
break | |
case 'BUTTON': | |
data[input.name] = input.value | |
break | |
} | |
return true | |
}) | |
await Promise.all(formdata) | |
delete data[''] | |
const output = [] | |
const boundary = '--Boundary-' + Math.round(Math.random() * 100000000) | |
for (const name in data) { | |
if (Array.isArray(data[name])) { | |
for (const item of data[name]) { | |
if (typeof item === 'object') { | |
output.push('Content-Disposition: form-data name="' + name + '" filename="' + item.file.name + '"\r\nContent-Type: ' + item.file.type + '\r\n\r\n' + item.binary.toString()) | |
} else { | |
output.push('Content-Disposition: form-data name="' + name + '"\r\n\r\n' + data[name]) | |
} | |
} | |
} else { | |
output.push('Content-Disposition: form-data name="' + name + '"\r\n\r\n' + data[name]) | |
} | |
} | |
return { | |
boundary: boundary, | |
object: data, | |
string () { return boundary + '\r\n' + output.join('\r\n' + boundary + '\r\n') + '\r\n' + boundary } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment