书接上回:如何实现付费下载功能?
现在已经实现的付费下载功能如下:
为了保护文件,还希望用户每次向后端发送下载文件的请求时,后端能生成一个一次性的链接,用户通过该链接下载一次文件后,该链接即失效。这样即使用户把链接发送给其他用户,其他用户也无法再通过该链接下载文件。
后端是 Express.js + MongoDB 的架构,要想实现这样的需求,实现的思路应该是怎样的呢?
1
pota 2022-11-08 15:12:33 +08:00
我觉得可以换个思路。CDN 防盗链的实效时间改成一个很短的时间(10 秒),这样在不修改逻辑的情况下最方便实现这个需求
|
2
fgwmlhdkkkw 2022-11-08 15:15:23 +08:00
前端先都下到内存里,然后再保存到系统文件,此时再向服务器报告下载完成。
|
3
dream4ever OP @pota 公司没有买 CDN ,成本不固定,领导不同意……
|
4
pota 2022-11-08 15:18:03 +08:00
@dream4ever #3 。。。就我体验来说,使用服务器带宽拉到可以下载比 oss+CDN 大部分情况下都贵很多
|
5
dream4ever OP @pota 现在业务体量小,所以暂时不考虑,等后面成本上来了再和领导说这个事,到时候他们更容易同意。
|
6
LinsVert 2022-11-08 15:20:17 +08:00
想到一个问题,如果这个链接用户没访问过,通过微信分享给了别人,因为微信会默认访问这个链接,会不会导致这个链接失效?
|
7
dream4ever OP |
8
w88975 2022-11-08 15:31:08 +08:00
你还得必须判断下载流是否读取完成, 不然下到一半网络出问题, 断点续传就失效了
|
9
lalalaqwer 2022-11-08 15:32:03 +08:00
对于用户要下载的文件可以临时生成一个 uid 和对应的文件路径存储在数据库中,链接带上 uid 就可以了。后端通过链接的请求去查找数据库有没有对应的 uid ,有的话就取对应的路径的文件发送回去,下载完事后删除 uid ,没的话就显示对应的无文件就行了。大概逻辑就这样吧,不一定非得查 uid 的有无,还可以多加字段控制 uid 是否有效,是否过期,记录链接的生成及下载时间等
|
10
dream4ever OP @w88975 文件体积小,普遍都不到 1M ,这个问题放到后面再考虑,不过依然感谢~
|
11
ysc3839 2022-11-08 16:01:00 +08:00
一次性链接的话存内存中都没啥问题
|
12
mercury233 2022-11-08 16:16:42 +08:00
伪需求,用户能把下载链接发给其他人,也就能把下载的文件发给其他人
基本上限制链接的有效时间就可以解决了 一次性链接的需求主要是某度网盘这种需要根据下载人区别限速,以及带广告的网盘的防盗链 |
13
dream4ever OP @mercury233 我这边也只能做网页这个层面能够控制的操作,用户拿到文件后会怎么做我们这边就不控制了。
|
14
PunchlY 2022-11-08 16:39:59 +08:00 via iPhone
用 jsontoken 储存唯一标识(再加一个随机字段
用户下载后将唯一标识变更 |
15
humbass 2022-11-08 16:55:58 +08:00
我们以前做过类似的:
- 每个下载 ID 在 redis 上做一个标记; - 用户下载的时候使用 XMLHttpRequest 接口缓存成 Blob 对象 - 当前 request 结束后,远程清除 redis 标记; 如果想做成断点续传、以及大的文件,还可以序列化 Blob 后,存到 IndexedDB ,前后端需要协调传了哪几个片段。 |
16
zy445566 2022-11-08 20:20:34 +08:00
启动一个 minio 服务不就好了
|
17
wellerman 2022-11-08 20:44:13 +08:00
你这目的无非防止人直接薅羊毛。1.下载必须登陆; 2.下载链接加个有效期,过期后重新获取。
|
18
IvanLi127 2022-11-08 22:13:09 +08:00
不应该生成一次性链接,而是应该通过前端调用接口下载到内存,然后再吐给用户。链接一次性,用户可以生多次吧?所以你的下载地址不能只通过 URL 判断,还得配合 Headers 或者 Body 中的身份信息。
|
19
gen900 2022-11-08 22:58:16 +08:00
链接一直都在,只是维护一个 TTL ,超时了请求返回 404 ,否则 sendFile
|
20
gen900 2022-11-08 23:01:09 +08:00
url “/download/tmp/:uuid” 通过 redis 维护每个 uuid 的有效性,key 过期了就 404
|
21
vone 2022-11-09 10:57:39 +08:00
https://developer.mozilla.org/zh-CN/docs/Web/API/Blob
去掉下载链接,点击按钮后用 ajax 发起请求,然后把返回数据转成 Blob ,通过浏览器保存。 |
22
dream4ever OP @vone 安卓微信有个问题,它只能调用其他 APP 来下载文件,安卓微信内的网页是没法下载文件的。就是因为这个问题,才不得不生成一个链接。
|