javascripthtmlcsvd3.js

Loading CSV data from Box into Javascript?


I have some regularly-updated CSV files on Box that I would like to display on a website. My plan was to create the table with html, then read the CSV file with d3 and update the contents of the table. If the CSV data were on GitHub, I could do something like this:

d3.csv(data_url).then(create_table);
function create_table(data) {
   <code to update a table>
}

However, that doesn't seem to work with a Box URL. I can generate a URL for the data on Box with the format "https://xxxxxxxx.box.com/shared/static/xxxxxxxxx.csv". Going to that link directly will download the CSV file, but inserting it into the code above produces a "Cross-Origin Request Blocked" error. Is this possible? Since the CSV files update hourly, it would be best if I could read directly from Box to my website, rather than moving the data elsewhere.


Solution

  • Box’s shared static file URLs (e.g. https://xxxxxxxx.box.com/shared/static/xxxxxxxxx.csv) do not send CORS headers, and:

    They force a file download via Content-Disposition: attachment

    They do not allow cross-origin AJAX/fetch/XHR requests like d3.csv()

    Hence, when you use D3 or fetch() from your website, the browser blocks it due to CORS policy.

    You can test this approach temporarily using a public CORS proxy like:

    const proxy = "https://cors-anywhere.herokuapp.com/";
    const url = proxy + "https://xxxxxxxx.box.com/shared/static/xxxxxxxxx.csv";
    
    d3.csv(url).then(create_table);
    

    OR

    Set up a backend (Node.js, Laravel, etc.) to periodically download the CSV from Box, store it locally, and serve it with proper CORS headers.

    Laravel example:

    Route::get('/csv-data', function () {
        $url = 'https://xxxxxxxx.box.com/shared/static/xxxxxxxxx.csv';
        $csv = file_get_contents($url);
        return response($csv)->header('Content-Type', 'text/csv');
    });
    

    Example in Node.js:

    const express = require('express');
    const axios = require('axios');
    const app = express();
    
    app.get('/csv-data', async (req, res) => {
      const boxUrl = 'https://xxxxxxxx.box.com/shared/static/xxxxxxxxx.csv';
      const response = await axios.get(boxUrl, { responseType: 'stream' });
      response.data.pipe(res);
    });
    
    app.listen(3000, () => console.log('Proxy server running'));
    

    React/D3 side:

    d3.csv('http://yourdomain.com/csv-data').then(create_table);