Sometimes, we may want to let users download a nested array with data as a CSV text file.
In this article, we’ll look at how to let users download a JavaScript array’s data as a CSV on the client-side.
Using the window.open Method
We can use the window.open
method to open a URL encoded string to let users download that to their computer.
For instance, we can write:
const rows = [
["name1", "new york", "abc"],
["name2", "san francisco", "def"]
];
let csvContent = "data:text/csv;charset=utf-8,";
for (const rowArray of rows) {
const row = rowArray.join(",");
csvContent += `${row}rn`;
}
const encodedUri = encodeURI(csvContent);
window.open(encodedUri);
We have the rows
nested array that we want to convert to a CSV string and let users download it.
To do the conversion, we first define the beginning of the csvContent
string which specifies the MIME type and the character set.
Then we loop through the rows
entries, join each row’s entries and append them to the csvContent
string with newline characters.
Then we call encodeURI
with the csvContent
string to encode it to a URL encoded string.
And finally, we can download the string as a file with window.open
.
We can also shorten the for-of with the map
method:
const rows = [
["name1", "new york", "abc"],
["name2", "san francisco", "def"]
];
const csvContent = `data:text/csv;charset=utf-8,${rows
.map((e) => e.join(","))
.join("n")}`;
const encodedUri = encodeURI(csvContent);
window.open(encodedUri);
We just call map
on rows
to map each row to a comma-separated string with join
.
Then we call join
on the mapped strings.
Download the file this way doesn’t let us set the file name.
To let us set the file name, we can create an invisible link and click on it programmatically.
To do that, we weiter:
const rows = [
["name1", "new york", "abc"],
["name2", "san francisco", "def"]
];
const csvContent = `data:text/csv;charset=utf-8,${rows
.map((e) => e.join(","))
.join("n")}`;
const encodedUri = encodeURI(csvContent);
const link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "data.csv");
document.body.appendChild(link);
link.click()
We call createElement
to create an a
element.
Then we set the href
to the encodedUri
.
And then we set the download
attribute to the file name with setAttribute
.
Next, we call appendChild
with the link
to attach it to the body.
And then we call click
on it to click it to start the download.
Save the Data as a Blob
We can save the data as a blob by rewriting the example above.
For instance, we can write:
const rows = [
["name1", "new york", "abc"],
["name2", "san francisco", "def"]
];
const csvContent = rows
.map((e) => e.join(","))
.join("n");
const blob = new Blob([csvContent], {
type: 'text/csv;charset=utf-8;'
});
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.setAttribute("href", url);
link.setAttribute("download", "data.csv");
document.body.appendChild(link);
link.click()
URL.revokeObjectURL(link.href)
We have the csvContent
string that only has the CSV string content.
Then we create a blob from it with the Blob
constructor.
In the 2nd argument of it, we set the type
to the data type of the blob.
Next, we call URL.createObjectURL
to create an encoded URL that we can download.
And we create the link element the same way as before, but with url
created from URL.createObjectURL
instead.
Also, we’ve to call URL.revokeObjectURL
to free up resources after the download is done.
Conclusion
We can let generate CSVs from nested arrays on client-side and let users download them with some JavaScript code.