Automatically import a local CSV file with Javascr

2020-02-29 11:36发布

问题:

My client wants a website that includes importing CSV data WITHOUT it being hosted on a server. The idea is so that their sales people can demonstrate their products without having web access or hosting set up on their PCs. They will also be able to update the data by exporting a new CSV file from the original Excel document, without any knowledge of HTML or Javascript.

I've found quite a few solutions online - like Papa Parse (http://papaparse.com/) but all of them require the user to select a file using <input type="file" />. As an example, the following script, using Papa Parse, works perfectly well:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Test CSV</title>
</head>
<body>
  <input type="file" />
</body>
<script src="js/jquery-1.10.1.min.js"></script>
<script src="js/jquery.parse.min.js"></script>
<script language="javascript">
  $('input').change(function(e) {
    $('input[type=file]').parse({
        complete: function(data) {
            console.log('Parse results:', data.results);
        }
    });
});
</script>
</html>

My problem is that I need to be able to hard-code the CSV file's location so that, when the web page is opened, the data is automatically displayed, without any further interaction by the user. Is this possible? Or have I overlooked something really basic?

回答1:

Hardcode the values inside a script tag of a non-javascript type such as text/csv then extract it with innerHTML or $("#unparsed").html()

<script type="text/csv" id="unparsed">
    url,title,size
    images/address-book.png?1354486198, Address Book, 1904 KB
    images/front-row.png?1354486198, Front Row, 401 KB
    images/google-pokemon.png?1354486198, Google Pokémon, 12875 KB
    ...
</script>

$(function parseData(){
    $("#file").hide();
    var data = $("#unparsed").html();
    var parsed = $.parse(data);
    $("#parsed").val(JSON.stringify(parsed));
})

http://jsbin.com/racanefi/10/edit

Hardcode the values inside a textarea.

$(function parseData(){
  $("#file").hide();
  var data = $("#unparsed").val();
  var parsed = $.parse(data);
  $("#parsed").val(JSON.stringify(parsed));
})

http://jsbin.com/racanefi/8/edit

OR

Store the value in localStorage.

var storage = localStorage;
var key = 'unparsed_text_file';

function getFile(){
$("#file").change(function(){
  var file = $(this).eq(0)[0].files[0],
    reader = new FileReader();
    reader.onload = function(e) {
      var text = reader.result;
      storage.setItem(key,text);
      parseData();
    };
    reader.readAsText(file);
});
}

function parseData(){
  $("#file").hide();
  var data = storage.getItem(key);
  var parsed = $.parse(data);
  $("#unparsed").val(data);
  $("#parsed").val(JSON.stringify(parsed));
}

if(storage.getItem(key))
  parseData();
else
  getFile();

http://jsbin.com/racanefi/6/edit

Browser Compatibility: http://caniuse.com/namevalue-storage

This is a rough draft, you should probably QA it well before implementing it.

edit: I had it backwards sessionStorage is temporary across sessions. localStorage is more permanent. I created a variable that lets you assign your storage to a var storage



回答2:

PapaParse is good quality stuff but for completion sake here's how it's done with jquery-csv

<html>
<head>
<meta charset="utf-8" />
<title>Demo - CSV-to-Table</title>
</head>

<body>
  <div id="inputs" class="clearfix">
    <input type="file" id="files" name="files[]" multiple />
  </div>
  <hr />
  <output id="list">
  </output>
  <hr />
  <table id="contents" style="width:100%; height:400px;" border>
  </table>

  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
  <script src="http://evanplaice.github.io/jquery-csv/src/jquery.csv.js"></script>
  <script>
    $(document).ready(function() {
      if(isAPIAvailable()) {
        $('#files').bind('change', handleFileSelect);
      }
    });

    function isAPIAvailable() {
      // Check for the various File API support.
      if (window.File && window.FileReader && window.FileList && window.Blob) {
        // Great success! All the File APIs are supported.
        return true;
      } else {
        // source: File API availability - http://caniuse.com/#feat=fileapi
        // source: <output> availability - http://html5doctor.com/the-output-element/
        document.writeln('The HTML5 APIs used in this form are only available in the following browsers:<br />');
        // 6.0 File API & 13.0 <output>
        document.writeln(' - Google Chrome: 13.0 or later<br />');
        // 3.6 File API & 6.0 <output>
        document.writeln(' - Mozilla Firefox: 6.0 or later<br />');
        // 10.0 File API & 10.0 <output>
        document.writeln(' - Internet Explorer: Not supported (partial support expected in 10.0)<br />');
        // ? File API & 5.1 <output>
        document.writeln(' - Safari: Not supported<br />');
        // ? File API & 9.2 <output>
        document.writeln(' - Opera: Not supported');
        return false;
      }
    }

    function handleFileSelect(evt) {
      var files = evt.target.files; // FileList object
      var file = files[0];

      // read the file metadata
      var output = ''
          output += '<span style="font-weight:bold;">' + escape(file.name) + '</span><br />\n';
          output += ' - FileType: ' + (file.type || 'n/a') + '<br />\n';
          output += ' - FileSize: ' + file.size + ' bytes<br />\n';
          output += ' - LastModified: ' + (file.lastModifiedDate ? file.lastModifiedDate.toLocaleDateString() : 'n/a') + '<br />\n';

      // read the file contents
      printTable(file);

      // post the results
      $('#list').append(output);
    }

    function printTable(file) {
      var reader = new FileReader();
      reader.readAsText(file);
      reader.onload = function(event){
        var csv = event.target.result;
        var data = $.csv.toArrays(csv);
        var html = '';
        for(var row in data) {
          html += '<tr>\r\n';
          for(var item in data[row]) {
            html += '<td>' + data[row][item] + '</td>\r\n';
          }
          html += '</tr>\r\n';
        }
        $('#contents').html(html);
      };
      reader.onerror = function(){ alert('Unable to read ' + file.fileName); };
    }
  </script>
</body>
</html>

Feature detection (ie which browsers won't work) is built-in, and the file has to be loaded via a file dialog because the sandbox protections block scripts from accessing the filesystem directly.

Disclaimer: I'm the author of jquery-csv.