前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >踩了坑:导出功能没做好,差点被投诉

踩了坑:导出功能没做好,差点被投诉

作者头像
烟雨平生
发布2023-03-07 10:53:32
5810
发布2023-03-07 10:53:32
举报
文章被收录于专栏:数字化之路

背景:

新上线的一个需求,研发期间,大家都做得比较辛苦。

同时,收到用户反馈功能功能不好用

问题描述:

反馈的问题是,导出的文件名像是乱码,看不懂。

比如多导出几次,导出的文件多了,就不容易找到想要的那个。

如果下载一个用户再自己重新命名一下,又会影响效率。

根据文件名不知道里面的内容

这就很烦了, 不改下名,不好找导出的文件。 改吧,又太麻烦。

用户又能拿这个功能怎么样,只能吐槽了

这是一个非功能的体验问题。

直接原因:

浏览器使用了默认的命名策略,如果没有指定下载文件名那么浏览器会这样这样:

将url上的非法字符去掉,然后拼一下。如果得到的字符串太长,还会进行截断处理。

原因分析:

用户执行导出后,后端返回的是一个包含了导出内容的oss地址,也就是一个Url。

前端直接把这个url放到<a>标签中。用户点击进行下载

下载时的交互

这种情况下,浏览器下载时展示在状态栏上的名字,浏览器就自由发挥了,目前浏览器的命名规则是将url上的非法字符去掉,然后拼一下。

下载的文件名

优化方案:

方案1:由服务器写入数据流的方式下载,同时由服务器指定一个自定义的文件名。

方案2:服务器返回存放业务数据的oss地址,前端指定一个自定义的文件名。

确定优化方案

最终选定了方案2。

原因是方案2改动最小,并且可以避免下载时导致业务数据缺失的问题。

客户都是用chrome,也规避了方案2的浏览器兼容性问题。

技术方案对比

方案1:

服务器返回数据流的方式

https://www.processon.com/view/6363c4d2e0b34d77dbcd4919

优点:

1. 可以由后端灵活自定义浏览器下载时的文件名。没有兼容性问题

2.代码实现简单。代码量少,实现简单

缺点:

1. 数据导出过程中如果出现异常,会出现只导出一部分数据的情况,整个下载过程并不会完全中断。用户没有办法分辨是否下载完成。

2. 服务器带宽打满后会影响其它功能的使用。服务器写数据到浏览器会占用服务器网卡的总带宽,如果打满,其它功能也用不了。可以把带宽想象成一座桥,大文件就像一个大卡车。

3. 影响到服务器的稳定性。大文件生成及传输过程会持续占用服务器内存。服务器的内存是有限的,下载大文件的功能占用了,其它功能就不能正常工作了。

4. 分布式环境中,增加了代码的复杂度。Feign或RestTempate在处理字节流时需要特殊的配置,在升级这些http客户组件时,也需要验证对这些已有功能的影响。

方案2:

使用oss作为数据中转站

https://www.processon.com/view/6363c4d2e0b34d77dbcd4919

优点:

1. 数据不会丢失。数据上传oss时报错时,整个导出就报错了,不会出现用户只拿到部分数据的情况

2. 不会占用服务器出口带宽。返回给前端的一个url,不管导出多大的文件,出口带宽都不会受到影响。

缺点:

1.兼容性问题。 在 HTML5 中,download 属性是 <a> 标签的新属性。

兼容性

定义和用法<a download="filename">filename 规定作为文件名来使用的文本。 该属性也可以设置一个值来规定下载文件的名称。所允许的值没有限制,浏览器将自动检测正确的文件扩展名并添加到文件 (.img,.xls,.doc,.pdf, .txt, .html, 等等)。 在 <a> 标签中必须设置 href 属性。 https://www.w3school.com.cn/tags/att_a_download.asp

2.需要下载的资源是同源的

同源策略(Same origin policy)是基于安全的考虑,是浏览器对JavaScript施加的安全限制,是浏览器最核心也最基本的安全功能。

简单地说只要在浏览器里打开页面,就默认遵守同源策略,目的是为了保证用户的隐私安全和数据安全。

那么什么是同源呢? 所谓同源是指两个 URL的"协议+域名+端口"三者都相同 https://www.runoob.com/tags/att-a-download.html

技术方案的详细设计

方案1:

按照http协议的要求,把业务数据转换成数据流写到HttpServletResponse

指定这个数据流的content-type:

代码语言:javascript
复制
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

指定数据流的打开类型为attachment,文件名filename:

代码语言:javascript
复制
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

show me the code

https://github.com/helloworldtang/spring-boot-cookbook/blob/master/learning-demo/src/main/java/com/tangcheng/learning/adapter/openapi/ExportController.java

方案2:

show me the code

https://github.com/helloworldtang/spring-boot-cookbook/blob/master/learning-demo/src/main/resources/templates/jsDownload.html

技术方案小结:

导出场景,服务器直接返回数据流到前端,要关注占带宽的情况。

如果是由前端指定下载的下载名,需要考虑兼容性问题。

最佳方案:

服务器返回oss url,且指定自定义文件名。

注意事项:

要解决文件名相同时,并发操作相互覆盖的问题。

需要通过url对相同文件名的oss数据在path的维度进行区分。

比如url是这种格式 ip/userId/yyyy/MM/dd/hh/mm/ss/SSS/一个随机数/自定义文件名

小结:

用户接触到的地方都是需要精心设计的。

用户关注的地方就是有价值的地方,需要投入资源做好。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 的数字化之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景:
  • 问题描述:
  • 直接原因:
  • 原因分析:
  • 优化方案:
  • 确定优化方案
  • 技术方案对比
  • 技术方案的详细设计
  • 技术方案小结:
  • 最佳方案:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档