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

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

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

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

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

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

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

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

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

    发布文章、商品,使用 id

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

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


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


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


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


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


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


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


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


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

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