Sitemap

FormData For JavaScript

4 min readMar 14, 2020

--

Tommy Callahan incorrectly answering a history test question. He fills in “Herbie Hancock” instead of “John Hancock”.
“Oh yeah, man. Alright, come on. Looks good to me.”

I recently performed a technical exercise wherein I had to upload files to a particular platform using their API. You often learn a lot when reading API documentation, and in this case I learned about FormData. It’s a simple concept, but I just hadn’t encountered it before and wanted to share the gist of what I learned for those finding themselves wearing the same shoes.

The exercise required me to upload a .strings file, which was another mystery to me. What I could ascertain was that the structure of the .strings file was key-value pairs, and appeared to be plain text. For example:

"key1" = "value1";
"key2" = "value2";
"key3" = "value3";

A little more investigation lead me to understand that each key-value pair is actually interpreted as a string. I have yet to discover every truth…

In order to upload the .strings file to the API, I chose to write scripts (in JavaScript) that would use fetch API to send HTTP POST requests. I had to construct the body schema of the request to successfully send the file, and I initially got some nice BIG 400 status validation errors. What to do?

* READ THE ERROR! * READ THE DOCUMENTATION!

There is a common tendency to become frustrated and disappointed by malfunction, but, in the world of programming, that malfunction usually comes with a side of information. Error messages are informative. Yes, they often look like the computed version of chicken scratch, but take a moment to read them. The error gibberish that I received led me to re-read the API documentation. Some documentation is more concise, clear, or organized than others. It can often be a helpless chore to sift through, but, even in the case of poopie documentation, there are still kernels of useful information.

Upon re-reading the API documentation, I discovered that the body schema of the HTTP POST request needed to be encoded as multipart/form-data. This MIME type is typically used when sending the values of a completed HTML form from browser to server, but can also be used to send files.

Get Dan Romans’s stories in your inbox

Join Medium for free to get updates from this writer.

From there, I knew that I needed to convert the .strings file in some way, or at least prepare it to meet the required request body schema. I then discovered the FormData API. The interface can be installed like any other npm package. It offers a FormData() constructor that creates a new FormData object. This is super handy, and has built in methods. One of which is .append(). This allows one to build a FormData object independent of an HTML form. While .append() can be simply used to load up the FormData object with key-value pairs akin to form inputs, I will share a simplified example of how to use the FormData object to send a file. In my opinion, a more useful application .

// import FormData API
const FormData = require('form-data')
// import File System API
const fs = require('fs')
// create new FormData object
const stringData = new FormData()
// use file system readFile function to buffer file
// this converts the file into streamable data
fs.readFile('./localizable.strings', (error, data) => {
if (error) console.log(error)
if (data) {
// append key-value pair of a file name and the file
// note that file should be File or Blob object
stringData.append('strings-file', data)
}
console.log('data type =', typeof stringData, '\n', stringData)
})
// log =>
data type = object
FormData {
_overheadLength: 143,
_valueLength: 1125,
_valuesToMeasure: [],
writable: false,
readable: true,
dataSize: 0,
maxDataSize: 2097152,
pauseStreams: true,
_released: false,
_streams:
[ '----------------------------533271838898765118606167\r\nContent-Disposition: form-data; name="file"\r\nContent-Type: application/octet-stream\r\n\r\n',
<Buffer 22 53 6d 61 72 74 6c 69 6e 67 20 54 69 70 73 22 20 3d 20 22 53 6d 61 72 74 6c 69 6e 67 20 54 69 70 73 22 3b 0a 0a 22 43 72 65 61 74 65 20 61 20 6c 6f ... >,
[Function: bound ] ],
_currentStream: null,
_insideLoop: false,
_pendingNext: false,
_boundary: '--------------------------533271838898765118606167'
}

How about that gibberish? Nice, huh? The FormData object, containing the data from the .strings file to be uploaded, can now be sent and successfully retrieved by the platform API.

const uploadStrings = (token) => {
fetch(`https://api.[platform name].com/files-
api/v2/projects/${projectId}/file`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Authorization': `Bearer ${token}`
},
body: stringData
})
.then(response => response.json())
.then(data => {
if (data.response.errors) console.log(data.response.errors)
if (data) console.log(data)
})
}

This is meant to be a rudimentary introduction to the capabilities of the FormData object. Explore the documentation and gain a better understanding of all its potential than I have! Making technologies communicate properly can be challenging, and I ended up having to write some creative, possibly extraneous, possibly inaccurate code to achieve all deliverables for the technical assessment; but it worked, and I started learning about something new to me. That is the joy of programming.

github.com/dangrammer
linked.com/in/danieljromans
danromans.com

--

--

Dan Romans
Dan Romans

Written by Dan Romans

// fullStackWebDeveloper, # software_engineer, Musician & Woodworker