Recipe 10.7
Exporting API Data With a Download Link
If you don’t want to worry about file permissions, or if you need wider browser support, you can convert the data to a Blob
and create an object URL, which you can then set as a link’s href
attribute. This will download the data like a normal file download from the browser.
Demo
Export
First name | Last name | Department |
---|---|---|
Loading...
Loading Users
|
Code
JavaScript
const exportLink = document.querySelector('#export-link');
let userList;
function loadUsers() {
// Make the request
return fetch('/api/users')
// Parse the response body as an object
.then(response => response.json())
// Handle errors, including network and JSON parsing errors
.catch(error => console.error('Couldn\'t fetch:', error.message));
}
loadUsers().then(data => {
userList = data;
document.querySelector('#loader').remove();
renderUsers(userList);
// Clean up the previous export data, if it exists.
const currentUrl = exportLink.href;
if (currentUrl) {
URL.revokeObjectURL(currentUrl);
}
// Need a Blob for creating an object URL
const blob = new Blob([JSON.stringify(userList, null, 2)], {
type: 'application/json'
});
// The object URL links to the Blob contents - set this in the link
const url = URL.createObjectURL(blob);
exportLink.href = url;
exportLink.classList.remove('d-none');
});
/**
* Renders an array of users in the user table.
* @param userList the array of users
*/
function renderUsers(userList) {
const tableBody = document.querySelector('#users tbody');
userList.forEach(user => {
renderUser(user, tableBody);
});
}
/**
* Renders a user object as a row in the user table.
* @param user the user object to render
* @param tableBody the table body to append the row to
*/
function renderUser(user, tableBody) {
const row = document.createElement('tr');
const firstName = document.createElement('td');
firstName.textContent = user.firstName;
row.appendChild(firstName);
const lastName = document.createElement('td');
lastName.textContent = user.lastName;
row.appendChild(lastName);
const department = document.createElement('td');
department.textContent = user.department;
row.appendChild(department);
tableBody.appendChild(row);
}
HTML
<a class="btn btn-primary d-none" id="export-link" download="users.json">
<i class="bi bi-box-arrow-down"></i> Export
</a>
<table id="users" class="table">
<thead>
<tr>
<th class="w-25">First name</th>
<th class="w-25">Last name</th>
<th class="w-25">Department</th>
</tr>
</thead>
<tbody>
<tr id="loader">
<td colspan="3" class="text-center p-4">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<div>Loading Users</div>
</td>
</tr>
</tbody>
</table>