skip to Main Content

The following code is suppose to import data into localStorage from a CSV file. The goal is that is should replace / update any existing localStorage data. I am using FileReader to import and was tryign to use JSON.stringify to save it to localStorage.

const fileInput = document.getElementById('csv');

const readFile = () => {
  const reader = new FileReader();
  
  reader.onload = () => {
    localStorage.setItem("entry_list", JSON.stringify(reader.result));
  }
  reader.readAsArrayBuffer(fileInput.files[0]);
};

fileInput.addEventListener('change', readFile);

Before import it is an empty array
After import is an empty object, but is should be an array with data from the CSV

I believe the issues is that is it trying to import this as an OBJECT rather than an ARRAY. How do I approach this problem or fix this issue?

2

Answers


  1. The issue is that you try to use JSON.stringify on an ArrayBuffer object. An ArrayBuffer does not have any enumerable object properties and hence becomes just {} when stringified.

    Either turn it into a regular array using JSON.stringify(Array.from(new Uint8Array(reader.result))) so you get every byte in the file as a number, or – my recommendation, since it’s easier to turn into a file again and smaller to store – don’t read it as ArrayBuffer in the first place but as data URI (which will use base64-encoding) by replacing readAsArrayBuffer with readAsDataURL.

    However, based on your comments, I am now quite sure that you would like to parse the CSV contents as well, instead of just storing the file. In this case take a look at one of the many CSV parsing packages out there, such as csv-parse.

    Here is an example how to use it:

    const fileInput = document.getElementById('csv');
    
    const readFile = () => {
      const reader = new FileReader();
      
      reader.onload = () => {
        const csvData = csv_parse_sync.parse(reader.result, { columns: true });
        // Commented out because sandboxed demo cannot access localStorage
        //localStorage.setItem("entry_list", JSON.stringify(csvData));
        
        // For demo purposes, show would normally get stored
        document.getElementById('output').innerText = JSON.stringify(csvData);
      }
      reader.readAsText(fileInput.files[0]);
    };
    
    fileInput.addEventListener('change', readFile);
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/sync.min.js"></script>
    
    <input type="file" id="csv">
    
    <pre id="output"></pre>

    Instead of a CDN like I used here, you would normally copy the relevant file from the package onto your server (or install the package there, if you can) and reference the file this way.

    Login or Signup to reply.
  2. CSV is plaintext, importing an array buffer is for binary data/files. You can just use the fetch API to read all of the text and then parse it into objects from CSV using a module perhaps:

    const fileInput = document.getElementById('csv')
    
    const update = async () => {
        const lines = (await fileInput.files[0].text()).split(/[rn]+/)
        const records = lines // convert CSV record to object here
        localStorage.setItem("entry_list", JSON.stringify(records))
    }
    
    fileInput.addEventListener('change', update) 
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search