小弟只写过前端,没写过后端,现在写个小项目需要后端的一些实现。有个逻辑不太清楚应该怎么实现。
文件上传使用 minio 做文件存储。当前端想上传文件时候,前端请求一个 api 给后端,后端生成一个预签名的 minio url ,前端拿到这个上传链接进行上传。
上传完成后,前端是否需要再调用一次接口,将上传完成这个动作通知后端。
虽然 minio 有 webhook 功能,支持上传完成后调用后端接口通知后端程序。但这样和前端是并行的。上传完成后需要将一些信息写入到数据库,比如数据库有一个 state 状态标志着是否上传完成,以及上传完成后的 minio 直链。
如果使用 webhook 这种,前端上传完成后会立即刷新页面,但此时后台还没有完成数据库更新操作,数据刷新会不及时。
但是如果使用再加一个 api 让前端调用,感觉有点复杂,一个上传逻辑需要 3 个接口请求。
所以最佳实践是什么样的?
1
realpg 1 天前
肯定要通知啊。工作嫌麻烦,不如回家躺平
|
2
Kinnikuman OP @realpg 我现在就是在家躺平呢,没事干。写一下代码打发时间。
|
3
seers 1 天前 via iPhone
用 mq 解耦啊
|
4
xfurther01 1 天前 2
具体流程如下:
1 、前端调用后端文件上传认证接口:CreateFile ,获取 s3 地址和临时认证信息。 2 、前端根据 CreateFile 接口获取的 s3 信息,使用 s3 sdk 上传文件。例如( https://aws.amazon.com/cn/developer/) 3 、前端调用后端文件上传完成通知接口:UpdateFile ,通知后端上传结果和文件名。 4 、前端调用后端 GetFile 获取文件下载地址。 |
5
shadowyue 1 天前 2
前端通知你和不通知你的情况你都要处理。
万一前端上传完文件刚好流量用完了呢 |
6
a949690645 1 天前
我认为不需要通知,数据库里不存关于文件的任何信息。
|
7
yyttrr 1 天前
搜一下阿里云 oss sts 上传
|
8
IvanLi127 1 天前
一般文件不是至少关联一个实体实例吗?文件传完前端不用让后端更新对应的实体字段?前面预签名是要临时权限,把业务逻辑分一部分写在那里面才叫麻烦...
|
9
xiaoming1992 1 天前 via Android 1
如果是自己的玩具项目,就没必要通知了,后端把上传密钥和 pathname 返回给前端,并直接把这个 pathname 存到数据库中,直接当成前端已上传成功(万一部分极端情况前端上传失败,就自己走编辑流程,重新从头上传一次呗)
|
10
neutrino 1 天前 via Android
建议后端调用文件储存接口,并处理回调。这样前端只要把文件扔给后端并等待 URL 返回就好
|
11
mumbler 1 天前
用 cursor ,把你需求说出来就行了
|
12
Kinnikuman OP |
13
qwertyzzz 1 天前
@Kinnikuman 哈哈哈
|
14
spritecn 1 天前 1
@a949690645 不通知会有一个问题,有些文件传了根本没用过,这些文件积压下来,时间长了有几百 G,根本就找不到
|
16
SingeeKing 1 天前
歪个楼,要怎么解决恶意用户调用上传接口上传了一堆文件不通知后端的;加个定时任务来检查 s3 里面有没有不该存在的文件吗
|
17
guanzhangzhang 1 天前
首先是权限问题,oss 有 sts ,就相当于临时身份
前端拿 sts 直接上传 oss ,分段上传后调用 complete 请求给后端 |
18
Nitromethane 1 天前 1
|
19
Oceanhime 1 天前
桶读权限开放的话,小心有人恶意 list 然后下载数据或者刷流量...
我接手过的项目都是把文件上传+回调的所有逻辑统一交给后端处理,前端只调用 /upload 然后显示状态即可。对于公开的项目,你不能确保前端一定不会出错,如果 callback 执行中断或者恶意被执行,往小了说可能会影响数据完整性,如果这个 callback 涉及到敏感逻辑,可能出现安全问题。 |
20
sagaxu 1 天前 2
不如把问题泛化一下,三方调用,客户端,后端,第三方,
1. 客户端请求后端,后端调用第三方生成凭据后返回给客户端使用。 2. 客户端拿着凭据调用第三方,完成后应当如何? 有两个通知途径, 1. 客户端通知服务端调用结果 2. 第三方回调通知服务端 第 1 种方式,实时性比较高,用户体验更好,但很容易因为客户端网络或者关闭页面,导致通知丢失。 第 2 种方式,实时性稍差,但可靠性很高,可以按照一定时间间隔多尝试几次通知。 第 3 种方式,属于 fallback 兜底,服务端周期性轮询未知状态的凭据,做相应处理。 第 2 种是必须的,实时性要求高,再加上第 1 种。 更常见的场景是微信支付宝的支付。 |
21
ugpu 1 天前
@SingeeKing
1.发起请求我要上传文件 1.1 验证前端的 token 文件长度 文件名称 等文件 文件归属用户 信息 1.2 服务器接收到 验证完成预生成一个文件 1.3 客户端开始上传服务器开始写入 1.4 客户端上传完成把预生成文件写入一个标记为完成状态 1.5 客户端拉取列表展示最新的文件列表 你说的这个在第一步就已经完成了. |
22
ugpu 1 天前
@sagaxu
看到你这个 早期的美团外卖就做过这种”蠢事“ 就是大规模应用场景几乎不能用客户端通知 美团外卖当时的是: 付款跳回 app 本身才通知支付完成->后台->商家有新的订单. 现在美团估计是双端都会通知. 做了锁处理接着执行后续逻辑. |
23
npe 1 天前
当然要,如果嫌麻烦,可以写一个 lambda ,由 S3 存储桶触发后端来更新数据库状态。
|
26
CyouYamato 1 天前
让后端管,前端不要老是想着这个那个.老老实实调样式和调接口就好了.
|
27
xiaogu2014 1 天前
首先。建议使用 webhook 。通知数据库改状态。不应该依赖前端告知。
遇到的问题是```前端上传完成后会立即刷新页面,但此时后台还没有完成数据库更新操作,数据刷新会不及时``` 前端上传完成。这个文件的状态还是`处理中`。 只有等到 db 状态改了才会变成`完成`。 前端上传完成 != 文件全部可用。 |
28
zhuweiyou 1 天前
两个步骤
1.上传文件 2.提交上传得到的 url 和其它表单字段 上传做成业务无关的操作, 没有所谓的通知 |
29
Habyss 1 天前
最常用做法是: 直接把文件丢给后端.
如果已经到考虑宽带问题了, 就不是常用做法了. 而且你是小项目, 应该还没到考虑后端服务器宽带问题的地步吧. |
31
FaiChou 1 天前 via iPhone
|
32
yooomu 1 天前
作为一个后端,个人经验是直接传给后端,让后端去存到对象储存。不要在前端放太多逻辑,幺蛾子多
|
33
dilu 1 天前
没明白为什么搞的这么复杂,一般来说用对象存储的话,都是前端请求后端获取一个短期有效的 token ,然后用这个 token 直接上传到对象存储,从而获得资源 url ,最后看用户是否提交而把 url 一起提交给后端
当然 minio 有没有临时 token 我不太清楚,建议翻一下官方文档 |
34
vincentWdp 1 天前
@xfurther01 我可以提供一个思路:
既然是 s3, 那可以提供 临时上传 token 给前端, 这个 token 给一个很小的权限, 比如你可以给每个用户提供一个 object key 前缀, 用户只能把文件上传到这个前缀下. 因此 token 也是限制到这个前缀, 这样避免用户乱传. 而且文件名尽量随机, 不然用户可能会对其他用户的文件做尝试. 第二就是, 后端提供文件地址拼接方法, 前端用 s3 sdk 上传成功后, 按照拼接方法把文件 url 拼接出来, 再传给后端. 前端胡乱拼接的数据不会污染其他用户的数据. |
35
keller 1 天前
文件应该是上传给后端,由后端来决定存储方式(本地、oss 、s3 、minio )
|
36
0xD800 1 天前 via Android
通知,定时清理没通知的文件。
另外通知的时候要带上业务 id 用于检验文件是否真实用到了。 没用到的定时清理。 不然不就随便白嫖 |
37
neoblackcap 1 天前 2
@xqiang 现在上传文件都是直接上传到 OSS 服务,后端只做元数据处理(写数据库记录)。具体的文件上传功能都是前端做的。
这样有一个极大的优点就是,文件上传并不占用服务器带宽。否则文件上传到国内的服务器,一个人就可以把那可怜的公网服务器带宽打满了。 |
38
yh7gdiaYW 22 小时 51 分钟前
@SingeeKing 我们是后端在文件表建一条记录,返回预签名上传链接,上传完成并且前端提交表单成功后,把文件表的状态改掉,定时扫状态不对的文件清理
|
39
yh7gdiaYW 22 小时 49 分钟前
@dilu 表单里有个上传文件的地方,有人一直在这上传但又不提交表单,不加上传完成的确认这些垃圾文件如何处理? 18 楼的临时桶是一种方案,但其实也挺麻烦的且对大文件不友好
|
40
dilu 22 小时 45 分钟前
@yh7gdiaYW 我们之前是先传到私有桶里面,用户自己看的话是带签名的,如果用户不提交,链接就永远是私有链接,分享出去也看不到。提交后在后端检查 url 是不是私有桶的,然后重新传到公有桶再替换 url
如果你不想搞这一套,可以用私有桶的短时间签名的方式,格式化存储图片等资源,需要用的时候,去对象存书获取一个临时的 sign ,有效期几分钟而已,这样即使对方获取了 url 转发出去也很快就失效了。 |
41
yh7gdiaYW 22 小时 36 分钟前
@dilu 你们这个私有桶看着跟楼上的临时桶用途是类似的,小文件这么做没问题,对传数 GB 甚至更大文件需求的话就不合适了,对象存储复制大文件的速度一般
|
43
sazima 18 小时 51 分钟前
用 formdata 一个接口就行。
|