Skip to content

Instantly share code, notes, and snippets.

@loilo
Last active January 9, 2019 13:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loilo/f6e0c8f89b8dd12ed0ea to your computer and use it in GitHub Desktop.
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
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