V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
howells
V2EX  ›  JavaScript

救助: 前端根据 api 请求后端返回数据,并把数据导出成 csv。现在的问题在后端返回的数据很多,会导致传输时间久,并且有可能会导致浏览器崩溃,实践中有没有什么好的办法去实现这种大数量的导出

  •  
  •   howells · 2021-02-23 14:16:20 +08:00 · 4279 次点击
    这是一个创建于 1371 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前端根据 api 请求后端返回数据,并把数据导出成 csv 。现在的问题在后端返回的数据很多,会导致传输时间久,并且有可能会导致浏览器崩溃,实践中有没有什么好的办法去实现这种大数量的导出。

    37 条回复    2021-02-24 16:36:12 +08:00
    lemonada
        1
    lemonada  
       2021-02-23 14:19:48 +08:00
    为啥不是后端生成 csv,给个地址前端让浏览器获取下载链接然后下载呢
    waiaan
        2
    waiaan  
       2021-02-23 14:19:55 +08:00
    后端直接生成文件
    howells
        3
    howells  
    OP
       2021-02-23 14:23:44 +08:00
    @lemonada 因为最开始数据量少的时候,就直接去拿了,然后前端根据组件去导出了,所以现在量大了之后,就还是在沿用这个思路。直接生成文件,我试试
    fucUup
        4
    fucUup  
       2021-02-23 15:17:41 +08:00 via Android
    Indexeddb 就是这个
    azcvcza
        5
    azcvcza  
       2021-02-23 15:18:14 +08:00
    1,分页去获取喽,一次拿一点,拿到最后自己拼起来 2,直接下 csv 文件
    nbhaohao
        6
    nbhaohao  
       2021-02-23 15:20:28 +08:00   ❤️ 2
    新增一个 “下载中心” 模块,每次生成文件就是发请求到后端,后端负责创建一个生成文件的内容。
    然后前端可以去“下载中心”去下载已经生成好的文件。
    jydeng
        7
    jydeng  
       2021-02-23 15:24:38 +08:00
    赞同 6L,加一个下载模块,后端生成完了,通过聊天工具通知。
    admin7785
        8
    admin7785  
       2021-02-23 15:39:17 +08:00 via iPhone
    后端生成文件,可以参考 Easyexcel 工具,导出很方便
    howells
        9
    howells  
    OP
       2021-02-23 16:09:16 +08:00
    @nbhaohao 这个生成的文件就还得存储下来是不,然后等你去点击下载?
    Python77
        10
    Python77  
       2021-02-23 16:10:34 +08:00
    后端生成文件
    NikoXu
        11
    NikoXu  
       2021-02-23 16:12:32 +08:00
    返回文件流不就行了 ,没必要保存成文件吧
    howells
        12
    howells  
    OP
       2021-02-23 16:14:16 +08:00
    @NikoXu 我想的是他这种设计是因为生成文件时间久,如果能直接生成文件流,应该就不用还多一个下载中心吧
    NikoXu
        13
    NikoXu  
       2021-02-23 16:17:59 +08:00
    文件流直接可以下载了
    howells
        14
    howells  
    OP
       2021-02-23 16:22:50 +08:00
    @NikoXu 不矛盾,能快速生成文件流,它就可以直接在点下载的,我根据的 6L 的方案 =》“每次生成文件就是发请求到后端,后端负责创建一个生成文件的内容” 我说这个是不是要保存下来,然后在去下载中心点下载,
    676529483
        15
    676529483  
       2021-02-23 16:25:36 +08:00
    其实只要后端实现个接口,设置请求头,返回文件流,前端标记为 download,浏览器就自动流下载流
    nbhaohao
        16
    nbhaohao  
       2021-02-23 16:26:28 +08:00
    @howells 是的,比如后端还可以做别的需求,例如文件只保留 7 天,然后前端去点击下载,下载的时候只要能拿到文件地址就可以了,比如一个 oss 地址。

    同时第一次点击“生成文件”的时候,后端的接口可以快速返回 response,即告诉用户,这个导出任务已经在执行了,然后接口慢慢去生成就可以了。
    nbhaohao
        17
    nbhaohao  
       2021-02-23 16:28:49 +08:00   ❤️ 1
    @howells 总结下来就是,“文件生成”的逻辑不要放在前端。
    其他答主的说法也都是对的,
    文件小的话,后端直接返回文件流,或者返回一个 url,然后前端下载就好了,
    文件大的话,最好考虑“下载中心”,就是先让这个请求快速结束,而不是强迫用户一定要开着浏览器慢慢等那个文件生成完毕。
    someonedeng
        18
    someonedeng  
       2021-02-23 17:05:02 +08:00
    还不如让后端做个导出,分分钟的事,返回文件流或对象储存连接都行
    w504391883
        19
    w504391883  
       2021-02-23 17:08:42 +08:00
    直接前台下载文件流,不要在代码中打开
    ivanshaoaz
        20
    ivanshaoaz  
       2021-02-23 17:09:54 +08:00
    做成异步任务也行 后端生成文件 前端轮训文件生成结果 后端生成文件成功返回个下载链接
    xiangyuecn
        21
    xiangyuecn  
       2021-02-23 17:12:59 +08:00
    参考 #15 楼,后端什么都不用干,响应头都不用动,前端把接口的调用改成浏览器自己去下载处理就目测 ok 了。

    最简单的办法: 把原有的 api 地址 直接粗暴的扔给 a[download] 标签手动 click 一下去触发浏览器去下载这个 url 的数据
    4771314
        22
    4771314  
       2021-02-23 17:15:19 +08:00
    肯定后端生成文件啊
    数据量大一点,前端就会卡住,很不友好
    后端可以异步生成文件,生成后通知前端去下载就可以了
    iikebug
        23
    iikebug  
       2021-02-23 17:23:36 +08:00
    webworker 或者 wasm 也可以考虑下
    Hilong
        24
    Hilong  
       2021-02-23 17:28:00 +08:00
    起一个 worker 来处理这个
    fengbjhqs
        25
    fengbjhqs  
       2021-02-23 18:14:08 +08:00
    kpi 怎么能让, 起个 worker 多线程来搞哇,除非内存泄露,请求超时可以让后端分批给数据
    Justin13
        26
    Justin13  
       2021-02-23 18:41:18 +08:00 via Android
    后端上 worker 导出 csv,成功后前端获取下载的 url 。点击下载。
    jones2000
        27
    jones2000  
       2021-02-23 20:37:44 +08:00
    生成文件同步到 CND 或云盘,然后下载就可以了。
    xieranmaya
        28
    xieranmaya  
       2021-02-23 21:05:13 +08:00
    流式处理。前端现在是可以实现的。
    golangLover
        29
    golangLover  
       2021-02-23 21:22:42 +08:00
    返回文件流+1
    golangLover
        30
    golangLover  
       2021-02-23 21:23:14 +08:00
    然后 header 是 attachment
    hantsy
        31
    hantsy  
       2021-02-23 21:33:40 +08:00
    生成临时文件(用 Redis 之类的,或者缓存工具,定时删除),数据源就稳定了。直接 Expose 这个文件给 Client 就可以了。
    tokyo2020
        32
    tokyo2020  
       2021-02-23 21:34:32 +08:00
    我的想法是 前端肯定有些参数列表,调 api 请求数据 getData 呢,后端可以先返回一个 queryId 。 大约 10s 后,前端带着 queryId 调用 api 再问询下, 后端服务器如果处理好了后,还可以把 queryId 的内容缓存下来呢。
    hantsy
        33
    hantsy  
       2021-02-23 21:35:10 +08:00
    另外写文件到 FTP 目录,客户端用 FTP 协议获取。

    银行支付行业,对账很多用 FTP 协议,定时处理。
    xuanbg
        34
    xuanbg  
       2021-02-24 08:59:58 +08:00
    后端导出文件并上传 oss,前端轮询结果,或者刷列表(需要实现一个导出文件管理功能)。
    wakzz
        35
    wakzz  
       2021-02-24 11:49:00 +08:00
    一般是两个方案
    1. 文件流:后端给前端传文件流,前端只要把流存成文件就可以了
    2. 异步文件: 后端异步生成文件,直接给前端一个最终文件的下载地址
    rodrick
        36
    rodrick  
       2021-02-24 11:57:29 +08:00
    文件流下载学到了
    zhuweiyou
        37
    zhuweiyou  
       2021-02-24 16:36:12 +08:00
    后端异步生成, 存到 OSS.

    前端轮询状态, 完成后 出现下载按钮.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5736 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 61ms · UTC 02:55 · PVG 10:55 · LAX 18:55 · JFK 21:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.