V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
abcbuzhiming
V2EX  ›  程序员

如何解决“上传了附件但是最后其实没用”这个问题?

  •  
  •   abcbuzhiming · 2023-10-13 09:34:18 +08:00 · 3659 次点击
    这是一个创建于 404 天前的主题,其中的信息可能已经有所发展或是发生改变。
    比如以论坛的发帖功能来讲,它有个上传附件功能,我上传了一个附件,但是我突然把这个页面关了,没点保存,于是这个上传的附件就是个废附件,实际没用,占空间。

    那么有什么方法可以实现的好一点,清除掉这个没用的附件。

    一个简单的思考方法,就是把上传的文件保存在一个临时目录里,然后当你要保存使用这个文件附件的实际内容的时候,移动这个文件到真正的保存目录。然后临时目录定期清理。

    但是这个方法仍然存在缺陷,因为现实里不是所有的表单页面,都像论坛发帖这个页面一样,当你点下提交,整个页面提交内容到服务器后,就会关闭(或跳转到另外的页面)。
    有一些表单页面很复杂,所以,允许用户一边保存,一边编辑,这类页面有个特点就是,点保存后只会有个提示告诉你提交了,你本人还是停留在这个编辑页面上。这种就没办法沿用上述那个[移动上传文件到正式保存路径]这个逻辑的。因为你挪动文件的路径后,第一就是页面访问这些文件的路径都会发生变化,这导致你必须更新本地页面上这些附件附图的访问路径,否则它们都会变成红 x 无法访问了。这种保存一次后,还必须更新页面上数据的方式,对某些有大量附件的表单特别不友好。

    所以,还有没有更好的方案?
    32 条回复    2023-10-13 16:02:59 +08:00
    minglanyu
        1
    minglanyu  
       2023-10-13 09:38:35 +08:00
    blob
    shaojz2005
        2
    shaojz2005  
       2023-10-13 09:39:47 +08:00
    上传有 2 种情况,一是提交前并未上传文件;二是选择文件后就上传了。现在的开发模式一般是第二种,遇到没用文件的问题,一般情况下是不管它,占用不了多大空间。

    如果确实觉得有影响,可以定期跑个脚本,清理这些未在数据库中引用的文件。
    paradoxs
        3
    paradoxs  
       2023-10-13 09:40:05 +08:00
    根据你自己的需求来弄呗, 如果你空间很紧张,那他退出页面的时候没提交附件,就立刻给他删了。
    samnya
        4
    samnya  
       2023-10-13 09:43:40 +08:00
    我们是上传的文件也要写道数据库 file 表,然后表单保存的是 file id
    这样的好处是可以检查到有没有引用文件,然后也可以映射,比如实际上是同时支持阿里云腾讯云 oss 或者服务器自存的,查 file 表之后才知道实际 url
    JamesR
        5
    JamesR  
       2023-10-13 09:45:31 +08:00
    1.定时脚本,每日跑一遍,删除创建时间超过 1 天的无用附件。
    2.每次上传附件的接口,上传完毕的同时创建一个 Job ,2~3 小时后,Job 自动删除这个附件。适合欧洲等有数据要求严格的服务器(不能保存客户数据)。
    yolee599
        6
    yolee599  
       2023-10-13 09:53:04 +08:00
    上传的时候记录下来文件路径,每天定时脚本扫描当天上传的文件,没有是使用就删除
    yimiaoxiehou
        7
    yimiaoxiehou  
       2023-10-13 09:53:08 +08:00   ❤️ 3
    引用计数啊,文件表里面进行引用计数,定期删除 0 的就行
    cp19890714
        8
    cp19890714  
       2023-10-13 09:53:57 +08:00
    统一文件事务管理,所有文件在一个专门的“文件管理”功能中,通过“是否已提交”字段标识该文件是否有效。
    * 文件上传后,正常存储,“是否已提交”为 false
    * 业务表单 submit 后,调用文件管理接口“commit”,修改字段”是否已提交“为 true 。
    * 定时任务,删除一段时间后依然无效的文件。
    nothingistrue
        9
    nothingistrue  
       2023-10-13 09:57:05 +08:00
    一般都是不管,因为存储成本真得很低。

    我的预想方案如下。把所有附件,先转换成「资源」表的一个记录。资源表负责存储附件的相对路径,外部只能通过资源 ID 去关联附件。然后你就可以在资源表中维护附件的状态、关联性等,以及延时或者定期清理没有外部关联的资源记录和其对应的文件。因为「资源」个数据库表,它可以跟主业务保持事务一致性。资源表跟附件本身的一致性则需要额外保证,一般也只是保证从资源表到附件的单向一致性——只需要先保存文件再插数据,同时禁止外部删除文件即可。如果需要保证资源表跟附件的完全一致性,那开发成本将非常高。此方案仅存在与预想,因为参与过的老项目压根不会改,新项目涉及到开发时间就连我自己都不会上这种方案。
    justfindu
        10
    justfindu  
       2023-10-13 10:12:33 +08:00
    文件表, 没有关联引用的, 用户上传的都删掉. 保留后台上传的素材
    brader
        11
    brader  
       2023-10-13 10:16:13 +08:00
    就用你那个临时目录方案就行了,写个定时脚本,定时清理临时目录里超过 24 小时的文件,这样不就不会影响正在进行的业务了
    pannanxu
        12
    pannanxu  
       2023-10-13 10:18:12 +08:00
    设计个附件库模块,有强迫症的用户会自己删除的
    dzdh
        13
    dzdh  
       2023-10-13 10:20:36 +08:00
    上传独立一个接口,放到附件表,返回文件 id

    发布文章、商品,使用 id

    使用过的附件,标记已使用

    定期清理表里上传多久没有使用的,配合 oss 类的更佳
    dzdh
        14
    dzdh  
       2023-10-13 10:21:55 +08:00
    以前 discuz 编辑器是 bbcode, 类似是 [attachment]123123[/attachment]
    wOuv7i4e7XxsSOR1
        15
    wOuv7i4e7XxsSOR1  
       2023-10-13 10:29:26 +08:00
    存储不值钱
    f14g
        16
    f14g  
       2023-10-13 10:32:27 +08:00 via Android
    相当于设计一套简单的“gc”系统😁
    unco020511
        17
    unco020511  
       2023-10-13 10:38:28 +08:00
    两种方案:
    1.不用管,现在存储资源费用低,不清理问题不大
    2.楼上说了,引用计数,然后定期清理
    dallaslu
        18
    dallaslu  
       2023-10-13 10:47:24 +08:00
    给附件设置一个过期时间
    akjarjash
        19
    akjarjash  
       2023-10-13 10:49:45 +08:00
    是不是搞技术没多久😄
    libook
        20
    libook  
       2023-10-13 10:54:25 +08:00
    一个草案,具体按照你的需求修改。
    一个附件表,一个附件引用表。
    附件成功上传就记录到附件表,记录路径等信息;帖子或表单每次添加这个附件都在引用表里记录一下,记录是哪个帖子、转帖、引用贴或表单使用了了哪个附件。
    定时任务定期对比两个表,找到没有被引用的附件,然后执行删除操作。可以排除最近几个小时上传时间的附件,避免用户正在编辑帖子或表单但还未发布的情况。
    janus77
        21
    janus77  
       2023-10-13 10:56:19 +08:00
    一般不建议这样搞。我有两个需求:
    1 如果我之前在文章里面引用了这个附件,后面修改的时候又去掉了,但是只是临时去掉,过一段时间又更新了把他加上去,怎么区分这种情况?
    2 如果我之前只是因为文件太大,想提前上传,文章并没有写好,想等下次写好的时候再去引用,怎么区分这种情况?
    tool2d
        22
    tool2d  
       2023-10-13 10:58:47 +08:00
    我个人会设置一个附件最后访问时间,超过时限后统一扔到冷储存里。
    beiranc
        23
    beiranc  
       2023-10-13 11:01:15 +08:00
    我们用的就是类似于引用计数的方案,然后定时清理
    orlando
        24
    orlando  
       2023-10-13 11:18:02 +08:00
    引用计数,定时 GC
    abcbuzhiming
        25
    abcbuzhiming  
    OP
       2023-10-13 11:26:15 +08:00
    @samnya 这个上传文件记录 file 表,,然后记录其引用的业务数据 id 的方式,我们曾经尝试过,它的弱点就是把上传文件这个行为和业务数据强相关了,你每次上传文件,保存数据后,必须更新文件记录表,把相关的业务数据 id 传进来。本来存储是个很独立的事情,结果现在存储部门还得管业务引用的事情,搞了几次后存储部门非常反感这个方案,在也是为啥这个方案最终没用长的原因


    @JamesR
    你的方案里存在一个问题,就是,我怎么知道哪些附件没用呢?之所以有 [挪动文件] 这个解决方案,其实就是在挪动的时候,把这一波和当前业务数据有关的附件 id ,全部移动到特定目录去,那么剩下的自然就不相关了,自然可以随便删,但是问题是这个方案它不够好,问题我顶楼说了。


    @yolee599 现在就是没有比较好的办法,确定哪些文件没有用,特别是文件比较多的时候


    @yimiaoxiehou 引用计数方案其实就是 samnya 的那个方案,这个方案需要建立文件 id 和对其引用的业务数据 id 之间的映射关系,存储部门非常反感这个方案
    abcbuzhiming
        26
    abcbuzhiming  
    OP
       2023-10-13 11:33:53 +08:00
    @cp19890714 你这个方案似乎比直接关联业务 id 和文件 id 的方案要好一点,至少我可以不管存储部门,直接在我业务部门这边自己建表,我会考虑一下这个方案


    @nothingistrue 也是我自己蛋疼,其实这个看起来的小问题,真想做好要考虑很多方面,团队之前也是倾向于不管的,我是自己闲得无聊,希望找到最优解


    @brader 临时目录方案有缺陷的,我顶楼说了的,遇到那种保存数据时候不跳转页面,仍然停留在当前编辑页面的表单,这种方案要吃瘪,因为移动文件会改变文件的访问 url ,间接导致页面引用地址需要变更。


    @akjarjash 就是因为搞久了才会胡思乱想,想找到一个便宜,简单,又优雅的方案解决这个看起来很小的问题


    @janus77 对,附件修改引用也是个比较头疼的问题
    abcbuzhiming
        27
    abcbuzhiming  
    OP
       2023-10-13 11:35:17 +08:00
    谢谢大家的解答,我综合了一下,看来还是引用计数比较合理一些,剩下的就是说服存储部门的人了。当然,也可能还是搞不定,就放弃了,毕竟就像楼上有人提到的,这年头存储确实不太值钱。
    yimity
        28
    yimity  
       2023-10-13 11:48:55 +08:00
    如果是富文本编辑器里面的图片,不能定制具体的标记例如 id 来引用图片,只是一个访问图片的地址。这种如何应对呢?
    yimiaoxiehou
        29
    yimiaoxiehou  
       2023-10-13 14:18:31 +08:00
    @abcbuzhiming 和存储部门有啥关系,这不都是业务部门自己的事么,存储部门只提供存储对象的唯一 id 和操作接口就行啊。引用关系什么的业务自己维护啊
    brader
        30
    brader  
       2023-10-13 14:41:10 +08:00
    @abcbuzhiming 我感觉你还是没有理解到我所说的东西,什么叫“临时目录”,我说的是删除一天以前的临时目录文件,你编辑什么表单一天都编辑不完?不提交?第二天回来就让你重新上传有什么毛病,如果你觉得一天不够,3 天、7 天,总够了吧
    abcbuzhiming
        31
    abcbuzhiming  
    OP
       2023-10-13 15:10:40 +08:00
    @yimiaoxiehou 我们提出建立上传附件和相关引用数据之间的关联这点后,技术部门的老大排版要求存储部门完成这个事情。存储部门就很反感,而如业务部门里的我要把这个事情接下来,需要顾忌业务部门的其它人愿不愿意,毕竟多一事不如少一事


    @brader 有一种表单,其内容比较多,一边编辑,则能够一边保存。保存后不会关闭表单界面,以允许用户继续编辑。那么,在这种 UI 下,如果你一点保存,就把临时目录下的所有文件移动了正式目录,这显然会改变这些文件的预览地址,那么表单界面上预览这些文件的 url 就必须跟着变,不变的话预览图片之类的东西就会变红×。所以临时目录这功能只适合那种,点了保存,表单 UI 就消失跳转,要编辑这条记录需要重新打开,这种场景。
    luzemin
        32
    luzemin  
       2023-10-13 16:02:59 +08:00
    当年也特别纠结这个问题,请教了一些大佬,大佬的回复都是:
    你管它干啥?!

    所以搞不好业内最佳实践就是不把这个问题当做问题。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5361 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 08:27 · PVG 16:27 · LAX 00:27 · JFK 03:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.