Express.js 生成一次性下载链接
书接上回:如何实现付费下载功能?
现在已经实现的付费下载功能如下:
用户在微信中支付成功后,保存微信所返回的订单信息和所购买文件的 id ,同时订单信息中还包含用户微信号的 openid ,用来唯一标识用户。
用户在前端发起下载请求时,后端 Express.js 查询订单表中是否有该用户的 openid 和和所下载文件的 id ,有的话就用 res.sendFile() 把文件发送给前端。
为了保护文件,还希望用户每次向后端发送下载文件的请求时,后端能生成一个一次性的链接,用户通过该链接下载一次文件后,该链接即失效。这样即使用户把链接发送给其他用户,其他用户也无法再通过该链接下载文件。
后端是 Express.js + MongoDB 的架构,要想实现这样的需求,实现的思路应该是怎样的呢?
我觉得可以换个思路。CDN 防盗链的实效时间改成一个很短的时间(10 秒),这样在不修改逻辑的情况下最方便实现这个需求
前端先都下到内存里,然后再保存到系统文件,此时再向服务器报告下载完成。
公司没有买 CDN ,成本不固定,领导不同意……
#3 。。。就我体验来说,使用服务器带宽拉到可以下载比 oss+CDN 大部分情况下都贵很多
现在业务体量小,所以暂时不考虑,等后面成本上来了再和领导说这个事,到时候他们更容易同意。
想到一个问题,如果这个链接用户没访问过,通过微信分享给了别人,因为微信会默认访问这个链接,会不会导致这个链接失效?
链接是在用户进行“点击下载按钮”这样的操作时才生成的,而不是加载页面时就获取。
并且后端也会判断用户是否通过该链接下载了文件,没有下载的话链接也不会失效。
你还得必须判断下载流是否读取完成, 不然下到一半网络出问题, 断点续传就失效了
对于用户要下载的文件可以临时生成一个 uid 和对应的文件路径存储在数据库中,链接带上 uid 就可以了。后端通过链接的请求去查找数据库有没有对应的 uid ,有的话就取对应的路径的文件发送回去,下载完事后删除 uid ,没的话就显示对应的无文件就行了。大概逻辑就这样吧,不一定非得查 uid 的有无,还可以多加字段控制 uid 是否有效,是否过期,记录链接的生成及下载时间等
文件体积小,普遍都不到 1M ,这个问题放到后面再考虑,不过依然感谢~
一次性链接的话存内存中都没啥问题
伪需求,用户能把下载链接发给其他人,也就能把下载的文件发给其他人
基本上限制链接的有效时间就可以解决了
一次性链接的需求主要是某度网盘这种需要根据下载人区别限速,以及带广告的网盘的防盗链
我这边也只能做网页这个层面能够控制的操作,用户拿到文件后会怎么做我们这边就不控制了。
用 jsontoken 储存唯一标识(再加一个随机字段
用户下载后将唯一标识变更
我们以前做过类似的:
- 每个下载 ID 在 redis 上做一个标记;
- 用户下载的时候使用 XMLHttpRequest 接口缓存成 Blob 对象
- 当前 request 结束后,远程清除 redis 标记;
如果想做成断点续传、以及大的文件,还可以序列化 Blob 后,存到 IndexedDB ,前后端需要协调传了哪几个片段。
启动一个 minio 服务不就好了
你这目的无非防止人直接薅羊毛。1.下载必须登陆; 2.下载链接加个有效期,过期后重新获取。
不应该生成一次性链接,而是应该通过前端调用接口下载到内存,然后再吐给用户。链接一次性,用户可以生多次吧?所以你的下载地址不能只通过 URL 判断,还得配合 Headers 或者 Body 中的身份信息。
链接一直都在,只是维护一个 TTL ,超时了请求返回 404 ,否则 sendFile
url “/download/tmp/:uuid” 通过 redis 维护每个 uuid 的有效性,key 过期了就 404
developer.mozilla.org/zh-CN/docs/Web/API/Blob
去掉下载链接,点击按钮后用 ajax 发起请求,然后把返回数据转成 Blob ,通过浏览器保存。
安卓微信有个问题,它只能调用其他 APP 来下载文件,安卓微信内的网页是没法下载文件的。就是因为这个问题,才不得不生成一个链接。
高中时期 10 PRINT "HELLO WORLD" 20 END 大学新生 program Hello(input, output) begin writeln…
贪便宜,海鲜市场找了充值 Pro 会员 价格 110 3.13 冲,今天 3.15 掉会员,买的时候说了会掉会员风险,结果怎么快 申请退款,拒绝了,客服介入,让我举证,真是…
为什么就没有 linux 可在 Pixel 上原是的跑呢? 当然这不是 linux 的问题,就是想了解下,是什么原因呢? ubuntu-touch 也只支持到 Pixel 3a…
合速度