节点js导出生成的json作为文件

时间:2016-02-10 18:00:34

标签: json node.js http express

我的节点服务器正在生成一个json对象/数组。我需要将其发送给用户,但不要在浏览器上显示,而是作为文件显示。我该怎么做?

我不认为将它写入文件然后使用res.sendFile()是正确的做法。

1 个答案:

答案 0 :(得分:1)

您只需添加标题Content-Type作为浏览器不会直接显示的内容,然后将内容作为附件下载。

如果您想为下载文件命名,那么您将不得不使用标题Content-Disposition

JSON对象可以简单地转换为字符串,并使用上面的两个标题发送。

以下是工作服务器代码。

http = require('http');
server = http.createServer( function(req, res) {

    /**************** This is the important part **************/
    res.writeHead(200, {
        'Content-Type': 'application/json-my-attachment',
        "content-disposition": "attachment; filename=\"my json file.json\""
    });

    var jsonObj = {"name":"Will McAvoy"};
    res.end(JSON.stringify(jsonObj));
});

port = 3000;
host = '127.0.0.1';
server.listen(port, host);
console.log('Listening at http://' + host + ':' + port);

application/json-my-attachment是一个由Content-Type组成的名称,因为浏览器无法识别它,它会尝试下载它。否则,您还可以添加标准标题Content-Type: application/octet-stream

修改

关于第二个问题,如何在下载文件时在POST请求中发送参数,可以使用HTML Form轻松完成。

当您使用AngularJS时,我假设您不希望通过提交表单来刷新页面。这可以使用IFrame来完成。只需使用Javascript更新IFrame的src属性即文件下载路径。

它解决了页面刷新问题,但我们无法仅使用IFrame发送POST请求with body

我们必须使用combination of Form and IFrame。 HTML表单有一个属性target,我们可以在其中指定IFrame的名称。表单可以指定要使用的表单参数,操作和HTTP方法。由于目标是IFrame,因此无法刷新当前页面。

注意:此方法的限制是您无法使用表单提交发送HTTP标头,但有一些hacks available

以下是工作代码。我使用Expressjs作为节点服务器。

<强> HTML

<button id="downloadFile">download file</button>
<form id="downloadForm" method="post" action="http://localhost:3000/download" target="downloadIframe" style="display:none">
    <input type="text" name="param1">
    <input type="text" name="param2">
</form>
<iframe id="downloadIframe" name="downloadIframe" style="display:none"/>

<强>的Javascript

$(function () {
    $("#downloadFile").click(function () {
        var form = $("#downloadForm");
        form.find("[name=param1]").val("hello");
        form.find("[name=param2]").val("world");
        form.submit();
    });         
});

NPM安装

npm install express
npm install body-parser

节点服务器

var express = require('express');
var bodyParser = require('body-parser');
var path = require('path');
var fs = require('fs');

app = express(),
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

port = process.env.PORT || 3000;

app.all("/*", function (req, res) {
    if(req.method = "POST" && req.url === "/download") {
        /**************** This is the important part **************/
        res.writeHead(200, {
            'Content-Type': 'application/json-my-attachment',
            "content-disposition": "attachment; filename=\"my json file.json\""
        });
        console.log("body : " + JSON.stringify(req.body));
        var jsonObj = {"name":"Will McAvoy"};
        res.end(JSON.stringify(jsonObj));
    } else {

        var filePath = req.url;
        filePath = (filePath === "/") ? "index.html" : filePath;
        filePath = path.join(__dirname, "public", filePath);
        console.log(filePath);
        fs.stat(filePath, function (err, stat) {
            if(!err) {
                res.sendFile(filePath);
            } else {
                res.writeHead(404);
                res.end("file not found");
            }
        });
    }
});

console.log("server started at : http://localhost:" + port);
app.listen(port);

**下载按钮上的服务器输出单击**

服务器起始于:http:// localhost:3000
body:{&#34; param1&#34;:&#34; hello&#34;,&#34; param2&#34;:&#34; world&#34;}