30

I am trying to refer to this code where a we are downloading a CSV file on click of a link.

$(document).ready(function () {

    function exportTableToCSV($table, filename) {

        var $rows = $table.find('tr:has(td)'),

            // Temporary delimiter characters unlikely to be typed by keyboard
            // This is to avoid accidentally splitting the actual contents
            tmpColDelim = String.fromCharCode(11), // vertical tab character
            tmpRowDelim = String.fromCharCode(0), // null character

            // actual delimiter characters for CSV format
            colDelim = '","',
            rowDelim = '"\r\n"',

            // Grab text from table into CSV formatted string
            csv = '"' + $rows.map(function (i, row) {
                var $row = $(row),
                    $cols = $row.find('td');

                return $cols.map(function (j, col) {
                    var $col = $(col),
                        text = $col.text();

                    return text.replace('"', '""'); // escape double quotes

                }).get().join(tmpColDelim);

            }).get().join(tmpRowDelim)
                .split(tmpRowDelim).join(rowDelim)
                .split(tmpColDelim).join(colDelim) + '"',

            // Data URI
            csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv);

        $(this)
            .attr({
            'download': filename,
                'href': csvData,
                'target': '_blank'
        });
    }

    // This must be a hyperlink
    $(".export").on('click', function (event) {
        // CSV
        exportTableToCSV.apply(this, [$('#dvData>table'), 'export.csv']);

        // IF CSV, don't do event.preventDefault() or return false
        // We actually need this to be a typical hyperlink
    });
});

But somehow, the downloaded file is named as download without extension in Chrome v35.0.1916.114 , one workaround was to change data:application/csv to data:text/csv, but that only helped in getting the extension correct in the downloaded file i.e. it now downloads as download.csv.

The issue with the download attribute still remains. I wanted to name my file as export.csv, but it still gives me download.csv.

Giacomo1968
  • 23,903
  • 10
  • 59
  • 92
Sudo
  • 559
  • 1
  • 8
  • 15
  • 6
    I was running Chrome 34. Downloaded as "export.csv", upgraded to 35 downloaded as "download". Seems like a chrome bug to me. – malkassem May 22 '14 at 20:04
  • Yes... so is there any workaround for this? – Sudo May 22 '14 at 20:19
  • Just file a bug and wait for a fix to be released (I'm running into this same issue). It will probably be very soon. If you can't wait you'll have to send the csv down to the server with an ajax request so you can serve it back up. – method May 22 '14 at 20:43
  • So can i use nodejs http proxy server and get it from there? if so can someone give me any pointers how to do it? – Sudo May 22 '14 at 23:10
  • http://stackoverflow.com/questions/13912198/anchors-download-property-is-not-working-on-some-pages-gmail seems to work see jsFiddle: http://jsfiddle.net/pnMH2/ – malkassem May 23 '14 at 13:20
  • 1
    I confirm this happens here too, only "download" without extension downloads, should be "export.csv" any quick fix on this or Google news about it ? – NenadP May 27 '14 at 14:51
  • 1
    This bug has been fixed in Chrome 36, released July 16, 2014. Your [JSFiddle](http://jsfiddle.net/terryyounghk/KPEGU/) now works again! – bunting Jul 18 '14 at 15:35

6 Answers6

29

So you should change this:

// Data URI
csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv);

$(this)
    .attr({
    'download': filename,
        'href': csvData,
        'target': '_blank'
});

To This

// Data URI
//csvData = 'data:text/csv;charset=utf-8,' + encodeURIComponent(csv), //old way
blob = new Blob([csv], { type: 'text/csv' }); //new way
var csvUrl = URL.createObjectURL(blob);

$(this)
.attr({
    'download': filename,
    'href': csvUrl
});

And it should work!

matsilva
  • 496
  • 4
  • 4
  • right, blob still works with download attribute correctly. here is a demo: http://html5-demos.appspot.com/static/a.download.html – Falcon Jun 13 '14 at 16:18
  • This works great! Probably an even better solution than using data – PW Kad Jun 29 '14 at 16:46
  • This should be the accepted solution imo. Works like a charm. – SchizoDuckie Jul 06 '14 at 14:38
  • 1
    I actually need `'target': '_blank'` to make it work...Chrome 37 – Ilan Biala Aug 26 '14 at 07:55
  • @Mathew Thanks, you saved my day. I use `var universalBOM = "\uFEFF"; //var uri = 'data:text/csv;charset=utf-8,' + encodeURIComponent(universalBOM + CSV); var blob = new Blob([universalBOM, CSV], {type: 'application/xls;charset=UTF-8', encoding:"UTF-8"}); //new way var csvUrl = URL.createObjectURL(blob);` – Vijay Shegokar Jun 19 '18 at 06:02
9

This is a bug in Chrome 35 reported in issue #377860.

Update: This bug was merged into issue #373182. You can click the star to tell the devs you think this issue should get fixed and also get notified of changes.

Typically the chromium team releases an update every 2 weeks so you can expect a fix soon since this is marked as Pri-1 which I assume means highest priority.

styfle
  • 16,664
  • 22
  • 73
  • 115
2

For me worked:

var content = "some content";
var link = document.createElement('a');
var blob = new Blob(["\ufeff", content]);
var url = URL.createObjectURL(blob);
link.href = url;
link.setAttribute('download', 'file.csv');
link.click();
vokabakov
  • 111
  • 1
  • 2
  • 1
    This is not working in iOS. If i want to make it work in iOS, then how can i make it? – Guru Jan 05 '16 at 04:48
1

Here is a bit that worked for me (in Chrome and Firefox). I'm building a xls file out of a table.

  function downloadInnerHtml(filename,elId,mimeType){
    var elHtml='<table border="1">'+document.getElementById(elId).innerHTML+'</table>';
    var link=document.createElement('a');
    mimeType=mimeType || 'application/xls';

    var blob=new Blob([elHtml],{type:mimeType});
    var url=URL.createObjectURL(blob);
    link.href=url;

    link.setAttribute('download', filename);
    link.innerHTML = "Export to CSV";
    document.body.appendChild(link);
    link.click();
  }

  $(document).on("click","#exportButton",function(){
    var date=new Date();
    var mm=date.getMonth()+1;
    var dd=date.getDate();
    var yy=date.getFullYear();
    var timeStamp=yy+""+((mm<10)?"0"+mm:mm)+""+((dd<10)?"0"+dd:dd);
    var fileName=timeStamp+'_Employees.xls';
    downloadInnerHtml(fileName,'mainEmployeeTable','application/xls');
  });

Hope that helps someone else...

--Charles

w3bguy
  • 2,062
  • 1
  • 17
  • 29
0

When I tried this code, I was not able to get results in IE plus this code only iterates over td, it will skip any th present in your table. I have modified the code to resolve both the issues I was facing:

$(document).ready(function () {
    function exportTableToCSV($table, filename) {

            var $rows = $table.find('tr'),
            tmpColDelim = String.fromCharCode(11),
            tmpHeadDelim = String.fromCharCode(11),
            tmpRowDelim = String.fromCharCode(0),
            colDelim = '","',
            headDelim = '","',
            rowDelim = '"\r\n"',

            csv = '"' + $rows.map(function (i, row) {
                var $row = $(row),
                $cols = $row.find('td');
                $heads = $row.find('th');

                var c = $heads.map(function (k, head) {
                    var $head = $(head),
                    text = $head.text();
                    return text.replace(/"/g, '""');
                }).get().join(tmpHeadDelim);

                var d = $cols.map(function (j, col) {
                    var $col = $(col),
                    text = $col.text();
                    return text.replace(/"/g, '""');
                }).get().join(tmpColDelim);

            return (c+d);

        }).get().join(tmpRowDelim)
            .split(tmpRowDelim).join(rowDelim)
            .split(tmpHeadDelim).join(headDelim)
            .split(tmpColDelim).join(colDelim) + '"';


        var ua = window.navigator.userAgent;
        var msie = ua.indexOf("MSIE ");

        // if Internet Explorer (10+)
        if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) {
            var blob = new Blob([decodeURIComponent(csv)], {
                    type: 'text/csv;charset=utf8'
            });
            window.navigator.msSaveBlob(blob, filename);
        }
        else {
            var link = document.createElement('a');
            var blob = new Blob([csv],{type:'text/csv;charset=utf8'});
            var url = URL.createObjectURL(blob);
            link.href = url;
            link.setAttribute('download', filename);
            document.body.appendChild(link);
            link.click();
        }
    }

    $("#fnExcelReport").on('click', function (event) {
        var args = [$('#tableContent'), 'Report.csv'];
        exportTableToCSV.apply(this, args);
    });
});

CodePen

Aakash Goplani
  • 335
  • 1
  • 7
  • 17
-1

append anchor tag using string add tag information in string and then append, it works for me for google chrome