请教下后端大佬,关于文件上传逻辑的实现

73 天前
Kinnikuman  Kinnikuman

小弟只写过前端,没写过后端,现在写个小项目需要后端的一些实现。有个逻辑不太清楚应该怎么实现。

文件上传使用 minio 做文件存储。当前端想上传文件时候,前端请求一个 api 给后端,后端生成一个预签名的 minio url ,前端拿到这个上传链接进行上传。

上传完成后,前端是否需要再调用一次接口,将上传完成这个动作通知后端。

虽然 minio 有 webhook 功能,支持上传完成后调用后端接口通知后端程序。但这样和前端是并行的。上传完成后需要将一些信息写入到数据库,比如数据库有一个 state 状态标志着是否上传完成,以及上传完成后的 minio 直链。

如果使用 webhook 这种,前端上传完成后会立即刷新页面,但此时后台还没有完成数据库更新操作,数据刷新会不及时。

但是如果使用再加一个 api 让前端调用,感觉有点复杂,一个上传逻辑需要 3 个接口请求。

所以最佳实践是什么样的?

5029 次点击
所在节点   程序员  程序员
43 条回复
ugpu
ugpu
73 天前
@SingeeKing
1.发起请求我要上传文件
1.1 验证前端的 token 文件长度 文件名称 等文件 文件归属用户 信息
1.2 服务器接收到 验证完成预生成一个文件
1.3 客户端开始上传服务器开始写入
1.4 客户端上传完成把预生成文件写入一个标记为完成状态
1.5 客户端拉取列表展示最新的文件列表

你说的这个在第一步就已经完成了.
ugpu
ugpu
73 天前
@sagaxu
看到你这个 早期的美团外卖就做过这种”蠢事“
就是大规模应用场景几乎不能用客户端通知
美团外卖当时的是: 付款跳回 app 本身才通知支付完成->后台->商家有新的订单.
现在美团估计是双端都会通知. 做了锁处理接着执行后续逻辑.
npe
npe
73 天前
当然要,如果嫌麻烦,可以写一个 lambda ,由 S3 存储桶触发后端来更新数据库状态。
xqiang
xqiang
73 天前
@neutrino +1 ,上传文件难道不是应该后端来处理吗
vikaptain
vikaptain
73 天前
@xqiang 这样会占用后端服务器的带宽。
我现在的操作是不标记是否完成,前端上传之前先获取上传地址,上传完成之后把文件地址给后端,后端保存文件地址。
CyouYamato
CyouYamato
73 天前
让后端管,前端不要老是想着这个那个.老老实实调样式和调接口就好了.
xiaogu2014
xiaogu2014
73 天前
首先。建议使用 webhook 。通知数据库改状态。不应该依赖前端告知。

遇到的问题是```前端上传完成后会立即刷新页面,但此时后台还没有完成数据库更新操作,数据刷新会不及时```
前端上传完成。这个文件的状态还是`处理中`。 只有等到 db 状态改了才会变成`完成`。

前端上传完成 != 文件全部可用。
zhuweiyou
zhuweiyou
73 天前
两个步骤
1.上传文件 2.提交上传得到的 url 和其它表单字段

上传做成业务无关的操作, 没有所谓的通知
Habyss
Habyss
73 天前
最常用做法是: 直接把文件丢给后端.

如果已经到考虑宽带问题了, 就不是常用做法了. 而且你是小项目, 应该还没到考虑后端服务器宽带问题的地步吧.
FaiChou
FaiChou
73 天前
@mumbler 是的 我就是用 cursor ,但我需要先了解下,说不定有更好的方案。
FaiChou
FaiChou
73 天前
yooomu
yooomu
73 天前
作为一个后端,个人经验是直接传给后端,让后端去存到对象储存。不要在前端放太多逻辑,幺蛾子多
dilu
dilu
73 天前
没明白为什么搞的这么复杂,一般来说用对象存储的话,都是前端请求后端获取一个短期有效的 token ,然后用这个 token 直接上传到对象存储,从而获得资源 url ,最后看用户是否提交而把 url 一起提交给后端

当然 minio 有没有临时 token 我不太清楚,建议翻一下官方文档
vincentWdp
73 天前
@xfurther01 我可以提供一个思路:
既然是 s3, 那可以提供 临时上传 token 给前端, 这个 token 给一个很小的权限, 比如你可以给每个用户提供一个 object key 前缀, 用户只能把文件上传到这个前缀下. 因此 token 也是限制到这个前缀, 这样避免用户乱传. 而且文件名尽量随机, 不然用户可能会对其他用户的文件做尝试.
第二就是, 后端提供文件地址拼接方法, 前端用 s3 sdk 上传成功后, 按照拼接方法把文件 url 拼接出来, 再传给后端. 前端胡乱拼接的数据不会污染其他用户的数据.
keller
73 天前
文件应该是上传给后端,由后端来决定存储方式(本地、oss 、s3 、minio )
0xD800
73 天前
通知,定时清理没通知的文件。
另外通知的时候要带上业务 id 用于检验文件是否真实用到了。
没用到的定时清理。
不然不就随便白嫖
neoblackcap
73 天前
@xqiang 现在上传文件都是直接上传到 OSS 服务,后端只做元数据处理(写数据库记录)。具体的文件上传功能都是前端做的。
这样有一个极大的优点就是,文件上传并不占用服务器带宽。否则文件上传到国内的服务器,一个人就可以把那可怜的公网服务器带宽打满了。
yh7gdiaYW
72 天前
@SingeeKing 我们是后端在文件表建一条记录,返回预签名上传链接,上传完成并且前端提交表单成功后,把文件表的状态改掉,定时扫状态不对的文件清理
yh7gdiaYW
72 天前
@dilu 表单里有个上传文件的地方,有人一直在这上传但又不提交表单,不加上传完成的确认这些垃圾文件如何处理? 18 楼的临时桶是一种方案,但其实也挺麻烦的且对大文件不友好
dilu
72 天前
@yh7gdiaYW 我们之前是先传到私有桶里面,用户自己看的话是带签名的,如果用户不提交,链接就永远是私有链接,分享出去也看不到。提交后在后端检查 url 是不是私有桶的,然后重新传到公有桶再替换 url

如果你不想搞这一套,可以用私有桶的短时间签名的方式,格式化存储图片等资源,需要用的时候,去对象存书获取一个临时的 sign ,有效期几分钟而已,这样即使对方获取了 url 转发出去也很快就失效了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1105486

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX