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

附件系统应该怎么设计比较好?

  •  
  •   dssxzuxc · 153 天前 · 2995 次点击
    这是一个创建于 153 天前的主题,其中的信息可能已经有所发展或是发生改变。
    假如我有 20 张以上的业务表,每张表需要一个或多个附件字段,比如 xxx 信息表,有一个证明材料字段,有个验收材料字段,都是可以上传多个附件的。那我该怎么设计附件系统比较好?
    我的初步设想是,首先一个附件主表 file,一个附件从表 file_detail,一对多,从表存文件的路径和具体信息,每个业务表的附件字段存 file_id,这样就能关联起来。但是开发的时候又犯难了,上传的时候,我这么设计文件上传又没办法关联到业务表(上传和表单提交是分开的)。我想到文件上传之后,我把 file_id 返回给前端,前端提交表单再一起提交上来。但是这样又有新的问题,如果用户想要分次上传,比如两张图片,他先上传了 1 张,然后再传另 1 张,就会返回两个 file_id 过来。
    我看了公司之前有个项目也涉及到附件,他是这么做的,附件表每多一个业务表就加一个字段,20 张业务表就是 20 个 idxxx 、idxxx 这样的字段,上传的时候把自己的主键存到对应字段,不过这样没办法业务表多附件字段,除非 idxxx 字段加后缀接着细分,而且数据库一堆 null 有点蛋疼。
    各位有什么好的建议吗?
    32 条回复    2021-12-16 14:07:57 +08:00
    thinkershare
        1
    thinkershare  
       152 天前   ❤️ 1
    这个问题不是很容易解决吗? 文件上传只做上传, 不要做任何逻辑就好了, 逻辑交给业务接口处理, 文件只返回临时存储的地址, 后面的文件上的业务由业务接口处理
    Ayanokouji
        2
    Ayanokouji  
       152 天前
    minio
    eason1874
        3
    eason1874  
       152 天前
    用户要填表,进入表单,你就初始化表单,就是往数据库插入一条空信息,返回业务 form_id 给前端(要检查有没有历史空表单,有应该直接返回或者删除后再创建,防止用户每次进入都创建一个空表单)

    用户填表时,单独上传文件,你连着表单名、字段名一起上传,成功写入文件后就把 file_id 关联到 form_id ,返回状态时也返回字段名,根据字段名填充 file_id 到表单,提交时再验证一下
    dssxzuxc
        4
    dssxzuxc  
    OP
       152 天前
    @eason1874 这样能实现,但是流程一下子复杂了好多
    aliveyang
        5
    aliveyang  
       152 天前
    业务表中为什么要有附件字段?不是一对多么
    xuelu520
        6
    xuelu520  
       152 天前   ❤️ 1
    首先你想复杂了。
    1 、附件上传是独立的,存附件表信息,返回附件表的 id 。
    2 、可以弄个通用关联表
    例如:
    业务类型 业务类型 ID 附件类型 附件 ID
    A 业务 1 A1 file_id
    B 业务 2 B1 file_id

    这样就不用动到业务表那边去
    gengchun
        7
    gengchun  
       152 天前
    @Ayanokouji OP 也没有提他用的是 S3 ,也没有提对象存储,也没有提自己做的是分布式应用。这是怎么联想到的?
    nekoneko
        8
    nekoneko  
       152 天前
    字段给个数组类型不行吗?
    Mac
        9
    Mac  
       152 天前
    是表设计还是存储设计?

    表就是简单的关联子表呗,分类完全可以用字段来替代,只记录上传后的文件名和上传者 ID ,文件直接放到存储目录下。

    存储设计我现在是用 /UPLOAD/上传人 /业务号 /随机文件名.xxx 来做存储的
    cp19890714
        10
    cp19890714  
       152 天前
    ## 一张表即可

    `id`
    `batch_no`
    `file_name`
    `file_type`
    `file_size`
    `url`
    `business_type`
    `expire_at`
    `active_flag`
    `del_flag`


    ## interface

    //打开新的 BatchNo, 返回 batchNo
    openBatchNo

    //添加文件到 BatchNo, 返回所有文件的执行结果
    upload(String batchNo, List<File> files));

    //可多次 commit. 每次 commit,激活本次提交的 file,其他 file 失活
    commitBatchNo(String batchNo, List<String> fileIds)

    get(String batchNo);

    delete(String batchNO)


    ## 说明
    * 1 个 batchNo 可以添加多个 file
    * file 可以无限次的追加到已有的 BatchNo 中.
    * 通过 active_flag 实现事务,只有 commit 后,file 才有效. 无效的 file 会被定时删除.
    * 业务表使用 batchNo 关联
    zoharSoul
        11
    zoharSoul  
       152 天前   ❤️ 1
    业务表直接存附件(文件)地址不完事了.
    弄个附件表干啥?
    fpure
        12
    fpure  
       152 天前
    建议直接存成一个 json 到数据库里
    Huelse
        13
    Huelse  
       152 天前
    我觉得怎么设计都是家常便饭,像提交表单一样,重要的是文件放在那里,建议一开始就做好独立存储的准备
    815979670
        14
    815979670  
       152 天前
    一个附件表即可,附件表存储 附件 id ,附件路径,附件的业务表,关联业务 id 信息。
    第一步,图片上次成功,写入附件路径,得到附件 id ,返回给客户端。
    第二步,业务执行保存操作,根据附件 id 附件业务表明和业务 id 写回附件表。

    第一步实现了通用上传附件,第二部实现了附件的信息补全。

    最后做一个定时任务,当附件表的附件上传超过一定时间(如 24 小时),但是没有回写 业务 id 的就是脏数据(上传了福附件但是没有保存的),定时清除数据和对应文件。
    janus77
        15
    janus77  
       152 天前
    附件只需要一张表,file 表就不要了,业务表就包含了 file 的功能。
    为什么业务表和附件表不能一对多?
    hingbong
        16
    hingbong  
       152 天前 via Android
    MySQL blob 直接存😏
    Valid
        17
    Valid  
       152 天前
    minio 直接用 s3 的 sdk
    dssxzuxc
        18
    dssxzuxc  
    OP
       152 天前
    @nekoneko 那样展示整页的表单数据就有点麻烦了,每行的多个数组分别做一次查询?还是一次性把所有的数组合并然后查出所有的附件,然后再多次遍历放到各自的业务列表里去?
    857681664
        19
    857681664  
       152 天前 via Android
    把附件信息以 json 数组的形式存进附件表,同时用 id 和 type 字段与相对应的业务表进行关联
    nekoneko
        20
    nekoneko  
       152 天前
    @zoharSoul #11 附件删除了怎么办
    nekoneko
        21
    nekoneko  
       152 天前
    @dssxzuxc #18 对呀
    nekoneko
        22
    nekoneko  
       152 天前
    @zoharSoul #11 附件可能有上传者,上传时间等等信息,也就没了
    zoharSoul
        23
    zoharSoul  
       152 天前
    @nekoneko #22 全追加到业务表上就行
    zoharSoul
        24
    zoharSoul  
       152 天前
    @nekoneko #20 删除了就把业务表上的附件相关字段清掉啊
    nekoneko
        25
    nekoneko  
       152 天前
    @zoharSoul #24 业务表只存了个地址,是要字符串匹配着清吗
    #23 那意思就是业务表存 json 呗
    nekoneko
        26
    nekoneko  
       152 天前
    @zoharSoul #24 你可能看漏了,楼主说了每张表有多个附件字段,每个字段可以有多个附件,我感觉你理解成每个字段只有一个附件了
    zoharSoul
        27
    zoharSoul  
       152 天前
    @nekoneko #26 嗯, 我的意思就是业务表存 json
    2i2Re2PLMaDnghL
        28
    2i2Re2PLMaDnghL  
       152 天前
    『关系型数据库里的数组需要转置一下存成多条记录』
    (这是 RDBMS 还没几个数组类型的时候说的)

    一对多就是把关系倒转,是附件表里带业务表的 ID 。
    neptuno
        29
    neptuno  
       152 天前 via iPhone
    上传文件是单独的功能,表单跟附件表可以一对多
    dssxzuxc
        30
    dssxzuxc  
    OP
       152 天前
    @815979670 这个可行,附件表里加上业务 id 、业务表名、业务字段名 3 个字段,不过插入字段名只能用硬编码,查询 sql 也是用硬编码拼接,而这个字段名对于业务 entity 是多余的,因为业务表不存附件表信息,那这个字段名我只能放 vo 类里面,感觉后期维护容易写出 bug
    815979670
        31
    815979670  
       151 天前
    @dssxzuxc 如果业务表不存附件信息的话,附件表必须存业务表名+业务 id 啊,不然怎么确定这个附件是属于那个业务表的?
    至于硬编码问题,如果你们对查询接口做了同意封装,应该可以通过传参 或者取表名的方式解决。
    unco020511
        32
    unco020511  
       151 天前
    文件上传做成与业务无关的服务,后期管理和切换都方便.业务这边直接存文件 url 就行,有个表来关联 file 和业务 id,你想怎么对应都可以
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3301 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 05:19 · PVG 13:19 · LAX 22:19 · JFK 01:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.