1

我需要将视图中显示的表格的内容下载为 CSV 文件。我有代码可以正确格式化表格的内容,以便可以将其存储为 .csv 文件(例如,列分隔符是逗号,表格的每条记录都在新行中)。

所以,在我的控制器中,我有以下代码:

window.location.href = '/download?data=' + encodeURIComponent($scope.csvString);

我将 NodeJs 用于服务器部分。在这里,我有以下路由处理程序:

app.get('/download', function (req, res) {
    var data = req.query.data;

    res.attachment('data.csv');
    res.setHeader('Content-Type', 'text/csv');
    res.end(data);
});

这工作得很好。下载工作正常,下载文件中的数据为完美的 CSV 格式。没有问题。

当表中的记录太多时,即数据量很大时,就会出现问题。因此,查询参数非常大,我假设它超过了限制,因此,GET 请求返回 400(错误请求)错误 - 请注意,根据我的分析,请求永远不会到达服务器,而是我观察到使用 Chrome 开发者工具请求失败。在浏览器中,URL 就是www.my_domain.com/download?data=the_lengthy_data. 就是这样。网页为空白/空,没有下载文件。

因此,我想知道如何下载冗长的数据?我遇到的所有示例都执行 GET 请求,因此我必须将冗长的数据作为查询参数传递。还有其他方法吗?

4

3 回答 3

5

不是您问题的真正答案,但从外观上看,您正试图“强制”下载客户端上生成的数据。然后在这种情况下,您可以创建一个数据 URI,其中直接包含数据。

你的角度 JS 模板:

<a href="data:base64,{{btoa(csvString)}}" download>Download CSV</a>

你的控制器:

$scope.btoa = function (val) {
    return btoa(val);
};

因此,您的 DOM 应如下所示:

<!-- The link contains data to the CSV string "a,b,c" -->
<a href="data:text/csv;base64,YSxiLGM=" download>Download CSV</a>

点击链接下载 CSV 文件。

编辑

您还可以使用名为FileSaver.js的库强制下载字符串。

因此,像往常一样,您将获得 CSV,但这次,您会将其转换为 BLOB。

var csvBlob = new Blob([$scope.csvString], { type: 'text/csv;charset=utf-8' });

然后,您可以调用 FileSaver.js 的saveAs函数。

saveAs(csvBlob, 'mydata.csv');
于 2013-09-06T17:22:03.880 回答
0

您对 URL 中的字符数限制是正确的。通常,冗长的数据通过正文传递,因为这在理论上没有字符限制。

但是,您应该避免尝试在 GET 请求中传递正文。发送方法上的 XMLHttpRequest 规范说- “如果请求方法是 GET 或 HEAD,请将数据设置为 null。”。

所以我建议,您使用 POST 请求并在正文中传递您的参数。因此,您还需要使用 app.post('download', ...) 重写处理程序,然后解析这些参数的 request.body。

同样根据我对您要执行的操作的理解, POST 似乎是更合适的 HTTP 动词,因为您提供了要由服务器处理和返回的数据块。

于 2013-09-06T17:08:49.397 回答
0

我们需要更改nodejs代码如下。节点代码

    function downloadableFile(req, res) {
        res.attachment(document.title);
        var bufferStream = new stream.PassThrough();
        // we read the file in buffer.
        bufferStream.end(new Buffer(document.buffer));
        return bufferStream.pipe(res);
    }

Angularjs 不理解二进制数据。所以在前端我们可以使用第三方工具,比如 FileSaver.js'

var csvBlob = new Blob([$scope.csvString], { type: 'text/csv;charset=utf-8' }); saveAs(csvBlob, 'mydata.csv');

或者我们可以像这样使用 angularjs 代码。Angularjs 代码。

    downloadDocument = function (path,id,type) {

    $http.get(path).then(function (data) {
    if (data.status === 404) {
        mpToastService.showToastHeader('error', 'Error downloading document');
    } else {
        var blob = new Blob([data.data],{
        type: type + ";charset=utf-8;"
        });
        $("#" + id).attr("href", window.URL.createObjectURL(blob));
        document.getElementById(id).click();
    }
    });
    }    

    //In html file, we need to include these two lines.

    <a ng-click="downloadDocument(document.path,document.id,document.mimeType)" >document.title</a>    
    <a id="document.id"></a>

此角码将在前端下载二进制数据,然后在流行的浏览器中弹出没有任何数据限制的下载模式。但通常这不是好的做法,除非客户有特殊要求。

于 2015-10-14T05:28:23.680 回答