开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
源起
昨天群友提了个问题,大意是后端把mp3文件转成了base64以json格式返回给前端,让前端完成自己下载文件这个功能
这个功能前端做也很简单,base64 转blob文件,然后用a标签下载即可
但是当时第一个念头就是,为啥要前端来做这个活,后端直接改一下header,返回文件地址不就下载了吗,当时就想在线battle了,转念一想还是先把这个功能实现,完成自己的本职工作,然后再来battle,我们可以不做这个功能,但不能够不会,不然都没法对线,接下来讲讲如何实现这个功能
下载Base64文件
下班回家之后打开群友发的文件,开始实现前端保存base64字符串为文件的功能
群友get的源文件的是一个MP3文件,这里就不方便放出来了,直接用一个gif来演示,下面的字符串是gif文件转base64后的字符串
const data = 'R0lGODlhIAA0APD/AP///wAAACH5BAUAAAIALAAAAAAgADQAAAJ4jI+pywsPo5TtzHurwRzq0HVfyI1kpp1opU5m66VwLDZ1zdylveNOv8sBMazh6kcEBZEon0KXFCZnpw01ZL0atS4lt/kFhyneMc0cyaIBanTb/B7Hw/NvnXvX5q97an/2BxPYMqhSWFXmlgi3KNdI92gXifdRuVAAADs='
解码
对base64进行解码 -> ASCII码字符串 -> uint8Array -> Blob
两行代码搞定
const data = new Uint8Array(atob(base64).split('').map((v) => v.charCodeAt()))
const blob = new Blob([data])
下载
保存下载就很简单了,用a标签下载即可
const $a = document.createElement('a')
$a.setAttribute('download','a.gif')
$a.href = URL.createObjectURL(blob)
$a.click()
当当当当,简简单单几行代码就完成了下载base64文件啦,各位看官记得点赞收藏,以后没准用的上
对线
前端的功能已经完成了,接下来讲讲为和后端对线,为什么不推荐用base64字符串让前端自己保存下载文件。
首先base64编码会让文件体积增大,和原文件大小比为4/3,这不是浪费流量吗?
后端要实现下载功能只需要修改一下header就好,非常方便,接下来演示一下如何在后端实现下载功能
首先起一个本地服务器,然后把gif返回给浏览器下载
既然都起了个服务器了,那就写两个接口,一个返回base64,一个返回二进制文件,具体代码在github,期待jym们的star⭐️,你的支持就是我最大的动力
接下来看一下如何实现下载功能
最关键的就是设置header Content-Disposition,attachment表示要下载,filename为下载的文件名
response.writeHead(200, {
"Content-Disposition": "attachment; filename=a.gif",
"Content-Type": "image/gif; ",
});
response.end(gif);
只要几行,后端下载功能就实现了,所以为啥不让后端来做这个功能呢
在上面那个仓库中还实现了后端返回base64的接口,和前端下载功能,有兴趣的同学可以看一看
另外推荐一下最近写的一个库@clean-js/api-gen, 根据YAPI,swagger2,swagger3等协议生成请求代码 ,而且还可以生成接口修改日志,查看新增,删除接口和字段,以防后端老哥们悄悄改文档,也是一款不错的battle工具
其他文章
什么?在React中也可以使用vue响应式状态管理
clean-js | 自从写了这个辅助库,我已经很久没有加过班了…
clean-js | 在hooks的时代下,使用class管理你的状态
clean-js | 手把手教你写一个羊了个羊麻将版
写给前端的数据库入门 | 序
写给前端的数据库入门 | docker & 数据库
有没有一种可能,你从来都没有真正理解async