12

I'm using a local in-browser database to store data. However I want to give users the ability to export that data to CSV.

While googling I found the solution with data urls - prepare the url with data. However in my case this is >1MB of data to generate each time the page (link) is rendered. Is there any alternative solution that would allow me to generate a file download from JavaScript, but does not require me to prepare the content upfront - only when user actually clicks the link?

In case it matters I'm using React to build my application..

kubal5003
  • 7,186
  • 8
  • 52
  • 90
  • Where exactly is the problem with converting the prepare-upfront solution (which I assume you already have?) to one that only does more or less the same thing(?) on click/demand ...? – CBroe Jun 03 '17 at 20:02
  • If I understood correctly you're suggesting to generate the anchor with data-url when the user clicked another button? Then fire a little bit of JS to actually click it? – kubal5003 Jun 03 '17 at 20:08
  • 1
    I'd try simply assigning the Data URI to `location.href` first, and see if browsers will let you do that ... – CBroe Jun 03 '17 at 20:10
  • Hmm that's actually a pretty clever thing to do. I had issues with loading 10mb(don't take the 10 too seriously..) to DOM, but this method probably won't result in attaching this to DOM.. – kubal5003 Jun 03 '17 at 20:15
  • dataURLs are limited to a couple megs. you can use [my download.js lib](https://github.com/rndme/download/) to download large files from client-side variables like strings and typed arrays. it uses window.URL where available and falls back to dataURLs, giving you the max possible download sizes without having to sweat the support details. – dandavis Jun 06 '17 at 13:02
  • Is [this](https://stackoverflow.com/a/44394958/6560716) what you want? –  Jun 06 '17 at 16:09

1 Answers1

13

Try a blob.

(no, not that kind)

demo

var blob = new Blob(["CSV DATA HERE"], {type: "text/csv"});
var url  = URL.createObjectURL(blob);
open(url);

Need to convert JSON to CSV?

demo

(https://stackoverflow.com/a/14966131/6560716)

var data = [["name1", "city1", "some other info"], ["name2", "city2", "more info"]];
var csvContent = "";
data.forEach(function(infoArray, index){
   dataString = infoArray.join(",");
   csvContent += index < data.length ? dataString+ "\n" : dataString;
}); 
var blob = new Blob([csvContent], {type: "text/csv"});
var url  = URL.createObjectURL(blob);
open(url);

Need to have a name for the file?

demo

var blob = new Blob(["CSV DATA HERE"], {type: "text/csv"});
var url  = URL.createObjectURL(blob);
var link = document.createElement("a");
link.setAttribute("href", url);
link.setAttribute("download", "filename.csv");
document.body.appendChild(link);
link.click();

Filename and JSON?

demo

var data = [["name1", "city1", "some other info"], ["name2", "city2", "more info"]];
var csvContent = "";
data.forEach(function(infoArray, index){
   dataString = infoArray.join(",");
   csvContent += index < data.length ? dataString+ "\n" : dataString;
}); 
var blob = new Blob([csvContent], {type: "text/csv"});
var url  = URL.createObjectURL(blob);
var link = document.createElement("a");
link.setAttribute("href", url);
link.setAttribute("download", "filename.csv");
document.body.appendChild(link);
link.click();
  • 2
    the filesaver.js library does a lot of this for you https://github.com/eligrey/FileSaver.js , the demo in the repo is a bit broken, but Ive replicated it here: https://codepen.io/anon/pen/rwVWZQ – Tim Marsh Jun 06 '17 at 16:27