简体   繁体   English

execCommand('SaveAs',true,'data.csv'); 在IE中无法正常工作

[英]execCommand('SaveAs', true, 'data.csv'); not working in IE

I'm using AngularJS with ng-grid. 我正在将AngularJS与ng-grid一起使用。 The CSV export plugin for ng-grid doesn't play nicely with IE, so we built a workaround using an iframe to grab the csv data and download. 用于ng-grid的CSV导出插件无法在IE上很好地使用,因此我们使用iframe构建了一种变通方法,以获取csv数据并下载。 However, the exeCommand function only saves as a text file, even when specifying a filename suffix of .csv. 但是,即使将文件名后缀指定为.csv,exeCommand函数也仅保存为文本文件。 All the data is in the text file, and when converted to a csv it works fine, but we need this file to download as a .csv from the start. 所有数据都在文本文件中,当转换为csv时,它可以正常工作,但是我们需要从头开始以.csv格式下载该文件。

I did find this MS bug that may be the source of the issue - curious if anyone can think of a solution: https://support.microsoft.com/en-us/kb/929863 我确实找到了可能是问题的根源的MS错误-好奇是否有人能想到解决方案: https : //support.microsoft.com/zh-cn/kb/929863

Thanks! 谢谢!

Code in question: 有问题的代码:

function ngGridCsvExportPlugin (opts) {
    var self = this;
    self.grid = null;
    self.scope = null;
    self.init = function(scope, grid, services) {
        self.grid = grid;
        self.scope = scope;
        function showDs() {
            var keys = [];
            // setup our map index of `field`: `displayName`
            var keyNames = {};
            for (var f in grid.config.columnDefs) { keys.push(grid.config.columnDefs[f].field);}

            // build a map of field i.e. {metric_name: "Metric Name", age: "Age"}
            for (var f in grid.config.columnDefs) {
                keyNames[grid.config.columnDefs[f].field] = grid.config.columnDefs[f].displayName;
            }
            var getCsvFileForIE = function(target) {
                var csvData = target.attributes["data-csv"].value;
                if ( ! supportsDataUri() ) {
                    csvData = decodeURIComponent(csvData);

                    var iframe = document.getElementById('csvDownloadFrame');
                    iframe = iframe.contentWindow || iframe.contentDocument;

                    csvData = 'sep=,\r\n' + csvData;

                    iframe.document.open("text/html", "replace");
                    iframe.document.write(csvData);
                    iframe.document.close();
                    iframe.focus();
                    iframe.document.execCommand('SaveAs', true, 'data.csv');
                } else {
                    if (console && console.log) {
                        console.log('Trying to call getCsvFileForIE with non IE browser.');
                    }
                }
            };

            var supportsDataUri = function() {
                var isOldIE = navigator.appName === "Microsoft Internet Explorer";
                var isIE11 = !!navigator.userAgent.match(/Trident\/7\./);
                return ! (isOldIE || isIE11);  //Return true if not any IE
            };
            var csvData = '';
            function csvStringify(str) {
                if (str == null) { // we want to catch anything null-ish, hence just == not ===
                    return '';
                }
                if (typeof(str) === 'number') {
                    return '' + str;
                }
                if (typeof(str) === 'boolean') {
                    return (str ? 'TRUE' : 'FALSE') ;
                }
                if (typeof(str) === 'string') {
                    return str.replace(/"/g,'""');
                }

                return JSON.stringify(str).replace(/"/g,'""');
            }
            function swapLastCommaForNewline(str) {
                var newStr = str.substr(0,str.length - 1);
                return newStr + "\n";
            }
            for (var k in keys) {
                // unwrap our mapping dictionary
                csvData += '"' + csvStringify(keyNames[keys[k]]) + '",';
            }
            csvData = swapLastCommaForNewline(csvData);
            var gridData = grid.data;

            for (var gridRow in gridData) {
                for ( k in keys) {
                    var curCellRaw;
                    if (opts != null && opts.columnOverrides != null && opts.columnOverrides[keys[k]] != null) {
                        curCellRaw = opts.columnOverrides[keys[k]](gridData[gridRow][keys[k]]);
                    //dbogart added this to handle null cases
                    } else if (gridData[gridRow] === null) {
                        curCellRaw = '';
                    } else {
                        curCellRaw = gridData[gridRow][keys[k]];
                    }
                    csvData += '"' + csvStringify(curCellRaw) + '",';
                }
                csvData = swapLastCommaForNewline(csvData);
            }
            var fp = grid.$root.find(".ng-grid-buttons");
            var csvDataLinkPrevious = grid.$root.find('.ng-grid-buttons .csv-data-link-span');
            if (csvDataLinkPrevious != null) {csvDataLinkPrevious.remove() ; }
            var csvDataLinkHtml = "<div class='ngHeaderButton2'></div><span class=\"csv-data-link-span\">";
            //csvDataLinkHtml += "<a class ='exportLink' href=\"data:text/csv;charset=UTF-8,";
            //csvDataLinkHtml += encodeURIComponent(csvData);
            //csvDataLinkHtml += "\" download=\"Export.csv\"><i class='fa fa-file-excel-o excel-icon'></i></a></span>" ;
            csvDataLinkHtml += " <a ";
            if ( ! supportsDataUri()  ) {
                csvDataLinkHtml += " data-csv=\"";
                csvDataLinkHtml += encodeURIComponent(csvData);
                csvDataLinkHtml += "\" onclick='getCsvFileForIE(this);' >";
            } else {
                csvDataLinkHtml += "href=\"data:text/csv;charset=UTF-8,";
                csvDataLinkHtml += encodeURIComponent(csvData);
                csvDataLinkHtml += "\" download=\"Export.csv\">";
            }
            csvDataLinkHtml += "<i class='fa fa-file-excel-o excel-icon'></i></a></span>" ; //End csv-data-link-span

            //csvDataLinkHtml += "CSV Export</a> &nbsp;&nbsp;";

            //csvDataLinkHtml += "</br></span>"; //End csv-data-link-span
            fp.append(csvDataLinkHtml);
        }
        setTimeout(showDs, 0);
        scope.catHashKeys = function() {
            var hash = '';
            for (var idx in scope.renderedRows) {
                hash += scope.renderedRows[idx].$$hashKey;
            }
            return hash;
        };
        scope.$watch('catHashKeys()', showDs);
    };
}

function getCsvFileForIE(target) {
    var csvData = target.attributes["data-csv"].value;
    if ( ! supportsDataUri() ) {
        csvData = decodeURIComponent(csvData);

        var iframe = document.getElementById('csvDownloadFrame');
        iframe = iframe.contentWindow || iframe.contentDocument;

        csvData = 'sep=,\r\n' + csvData;

        iframe.document.open("text/html", "replace");
        iframe.document.write(csvData);
        iframe.document.close();
        iframe.focus();
        iframe.document.execCommand('SaveAs', true, 'data.csv');
    } else {
        if (console && console.log) {
            console.log('Trying to call getCsvFileForIE with non IE browser.');
        }
    }
};

function supportsDataUri() {
    var isOldIE = navigator.appName === "Microsoft Internet Explorer";
    var isIE11 = !!navigator.userAgent.match(/Trident\/7\./);
    return ! (isOldIE || isIE11);  //Return true if not any IE
};

This works for me on Windows 7 IE 11, see https://stackoverflow.com/a/24417650/1198657 这适用于Windows 7 IE 11上的我,请参阅https://stackoverflow.com/a/24417650/1198657

if (window.navigator.msSaveOrOpenBlob) {
  blobObject = new Blob([csvData]);
  window.navigator.msSaveOrOpenBlob(blobObject, 'Export.csv');
}

I was actually having the same problem, but after looking into the source code for ui-grid (in the ui-grid.js file), I found that the version check of IE wasn't working correctly 我实际上遇到了同样的问题,但是在查看ui-grid的源代码(在ui-grid.js文件中)之后,我发现IE的版本检查无法正常工作

    downloadFile: function (fileName, csvContent, exporterOlderExcelCompatibility) {
      var D = document;
      var a = D.createElement('a');
      var strMimeType = 'application/octet-stream;charset=utf-8';
      var rawFile;
      var ieVersion;

      //Check if IE9 or below
      ieVersion = this.isIE();
      if (ieVersion && ieVersion < 10) {
        var frame = D.createElement('iframe');
        document.body.appendChild(frame);

        frame.contentWindow.document.open("text/html", "replace");
        frame.contentWindow.document.write('sep=,\r\n' + csvContent);
        frame.contentWindow.document.close();
        frame.contentWindow.focus();
        frame.contentWindow.document.execCommand('SaveAs', true, fileName);

        document.body.removeChild(frame);
        return true;
      }

      // IE10+
      if (navigator.msSaveBlob) {
        return navigator.msSaveOrOpenBlob(
          new Blob(
            [exporterOlderExcelCompatibility ? "\uFEFF" : '', csvContent],
            { type: strMimeType } ),
          fileName
        );
      }

So the ieVersion was returning true (which apparently in JS is less than 10...) 所以ieVersion返回的是true (显然在JS中小于10 ...)

Since I was looking for it to work in 11, I was able to comment this out and it worked fine! 因为我一直在寻找它可以在11年内使用,所以我可以对此进行评论,并且效果很好! But if you need it to work below 9, you can switch the order of these two functions. 但是,如果您需要它在9以下运行,则可以切换这两个功能的顺序。 The code is correct on the ui-grid.info site as of 6/3/2016 截至2016年6月3日,该代码在ui-grid.info网站上正确无误

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM