当前位置: 首页 > 面试题库 >

如何使客户端下载动态生成的非常大的文件

李飞翼
2023-03-14
问题内容

我有一个导出功能,可以读取整个数据库并使用所有记录创建一个.xls文件。然后将文件发送到客户端。

当然,导出完整数据库的时间需要很多时间,并且该请求很快会因超时错误而结束。

处理这种情况的最佳解决方案是什么?

例如,我听说过有关使用Redis进行队列的操作,但这需要两个请求:一个用于启动将生成文件的作业,第二个用于下载生成的文件。

来自客户端的单个请求是否可能?


问题答案:

Excel导出:

使用流。以下是一个大概的想法:

  1. 使用exceljs模块。因为它具有针对此确切问题的流API。

    var Excel = require('exceljs')
    
  2. 由于我们正在尝试启动下载。编写适当的标题以响应。

        res.status(200);
    res.setHeader('Content-disposition', 'attachment; filename=db_dump.xls');
    res.setHeader('Content-type', 'application/vnd.ms-excel');
  1. 创建一个由Streaming Excel writer支持的工作簿。提供给writer的流是服务器响应。
        var options = {
        stream: res, // write to server response
        useStyles: false,
        useSharedStrings: false
    };

    var workbook = new Excel.stream.xlsx.WorkbookWriter(options);
  1. 现在,所有输出流均已设置。对于输入流,最好使用将查询结果/光标作为流提供的DB驱动程序。

  2. 定义将1个表转储到1个工作表的异步函数。

       var tableToSheet = function (name, done) {
        var str = dbDriver.query('SELECT * FROM ' + name).stream();
        var sheet = workbook.addWorksheet(name);

        str.on('data', function (d) {
            sheet.addRow(d).commit(); // format object if required
        });

        str.on('end', function () {
            sheet.commit();
            done();
        });

        str.on('error', function (err) {
            done(err);
        });
    }
  1. 现在,让我们使用异步模块的mapSeries导出一些数据库表:
        async.mapSeries(['cars','planes','trucks'],tableToSheet,function(err){
       if(err){
         // log error
       }
       res.end();
    })

CSV导出:

对于单个表/收集模块的CSV导出,可以使用fast-csv:

    // response headers as usual
    res.status(200);
    res.setHeader('Content-disposition', 'attachment; filename=mytable_dump.csv');
    res.setHeader('Content-type', 'text/csv');

    // create csv stream
    var csv = require('fast-csv');
    var csvStr = csv.createWriteStream({headers: true});

    // open database stream
    var dbStr = dbDriver.query('SELECT * from mytable').stream();

    // connect the streams
    dbStr.pipe(csvStr).pipe(res);

现在,您正在将数据从数据库流式传输到HTTP响应,并快速将其转换为xls / csv格式。无需将全部数据缓冲或存储在内存或文件中。



 类似资料:
  • 我有一个php脚本,它将文件流式传输到客户端。 当我只需点击下载链接(例如,file.php?=id{file-id})时,下载就开始了,但所有数据都进入RAM。这样做的问题是当用户的RAM已满时,下载就会停止。我说的是AVG。100GB文件。 最快的解决办法是什么?GoogleDrive/OneDrive等如何做到?

  • 我是stackoverflow的新手,因此这是我的第一篇文章。请原谅我英语不好。。。我花了几个小时在相关的话题上,但没有一个能满足我的需要。我正在编写一个通讯簿,我希望我的用户能够随时下载pdf联系人列表。一切似乎都很顺利,但实际上客户端从未下载pdf文件,尽管我可以在使用chrome开发者工具的请求中看到它。这是我的密码: 当检查响应时,我得到如下结果: 有没有人好心告诉我出了什么事?

  • 问题内容: 鉴于这些问题 ,如果仍然存在,我深表歉意。这是该问题的另一个版本。 我的angular 1.5.X客户端为我提供了标题列表,每个标题都有一个关联的文件。我的Node 4.X / Express 4.X服务器使用该列表,获取文件位置,使用npm中的express-zip创建一个zip文件,然后将该文件流式传输回响应中。然后,我希望我的客户端启动浏览器的“下载文件”选项。 这是我的客户代码

  • 在有人说“重复”之前,我只想确保大家知道,我已经回顾了这些问题: 1) 使用angular和php,不确定这里发生了什么(我不知道php):下载zip文件并从angular方法触发“保存文件”对话框 2) 什么都做不到:如何使用angular下载zip文件 3) 这个人已经可以下载了,这已经超过了我想弄明白的点:从一个按钮动作触发的角度下载外部zip文件 4) 这个问题没有答案:下载。nodejs

  • 问题内容: 首先,我希望您知道我已经可以连接到Web服务服务器。我问这个问题是因为我想对wsimport生成的客户端如何工作有更深入的了解。根据我的研究,wsimport使用JAXWS。请注意,我对JAXWS不了解。 我使用wsimport生成了客户端。我使用的WSDL来自Axis2 Web服务,并由Axis2自动生成。下面的类是wsimport的结果: 下 下 通过上面的类,我可以确定其中包含W

  • 在做其他事情之前,我想让你知道我已经可以连接到web服务服务器了。我问这个问题是因为我想更深入地了解wsimport生成的客户端是如何工作的。根据我的研究,wsimport使用JAXWS。请注意,我不了解JAXWS。 我使用wsimport生成了我的客户机。我使用的WSDL来自Axis2 web服务,由Axis2自动生成。下面的类是wsimport的结果: 在下 在下 通过上面的类,我可以看出包含