【问题标题】:Node js export generated json as fileNode js将生成的json导出为文件
【发布时间】:2016-02-12 00:17:44
【问题描述】:

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

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

【问题讨论】:

    标签: json node.js http express


    【解决方案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 的名称。 Form 可以指定要使用的表单参数、动作和 HTTP 方法。由于目标是 IFrame,因此不会刷新当前页面。

    注意:此方法的局限性在于,虽然有一些hacks available,但您不能随表单提交一起发送HTTP标头。

    以下是工作代码。我使用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
    正文:{"param1":"hello","param2":"world"}

    【讨论】:

    • 你能告诉我在角度控制器端做什么吗?因为响应来了,所以我尝试使用 get。但我需要发送 POST。
    • 下载文件需要发送post请求吗?
    • 是的,我发送了几个参数,根据这些参数处理数据,然后发送json文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    • 1970-01-01
    • 2015-07-03
    • 2022-01-24
    • 2021-08-28
    相关资源
    最近更新 更多