Project

General

Profile

iMIS 文档管理模块设计

设计
11/07/2020

背景:在新的imis云框架下,文档管理作为单独的服务模块支撑整个iMIS文档、附件的存储,采用fastdfs来实现

fastDFS

关于fastDFS,详情见 https://www.jianshu.com/p/1c71ae024e5e

FastDFS是一款开源的轻量级分布式文件系统纯C实现,支持Linux、FreeBSD等UNIX系统类google FS,
不是通用的文件系统,只能通过专有API访问,目前提供了C、Java和PHP API为互联网应用量身定做,
解决大容量文件存储问题,追求高性能和高扩展性FastDFS可以看做是基于文件的key value pair存储系统,
称作分布式文件存储服务更为合适。

tracker-server:
跟踪服务器, 主要做调度工作, 起负载均衡的作用。 在内存中记录集群中所有存储组和存储服务器的状态信息, 
是客户端和数据服务器交互的枢纽。 相比GFS中的master更为精简, 不记录文件索引信息, 占用的内存量很少。

storage-server:
存储服务器( 又称:存储节点或数据服务器) , 文件和文件属性( metadata) 都保存到存储服务器上。
 Storage server直接利用OS的文件系统调用管理文件。

group:
组, 也可称为卷。 同组内服务器上的文件是完全相同的 ,同一组内的storage server之间是对等的, 文件上传、 删除等操作可以在任意一台storage server上进行

meta data:
meta data:文件相关属性,键值对( Key Value Pair) 方式,如:width=1024, heigth=768

对于Java客户端调用等,采用开源 FastDFS-Client 1.26.5

底层服务和基本接口:

// 上传文件
1、StorePath uploadFile(InputStream inputStream, long fileSize, String fileExtName);
//下载文件
2、byte[] downLoadFile(String path);
// 删除文件
3、void deleteFile(String filePath);

iMIS 云平台文档管理模块

数据库表:

km_file 文件实体表

字段 类型 描述
id varchar 主键
folderId varchar 文件夹id,km_folder表主键
companyId varchar 公司id
fileType varchar 文件类型,pm、km、dl
name varchar 文件名
fileExtension varchar 文件扩展名
title varchar 文件标题
description varchar 描述
keyword varchar 关键字
creator varch 创建者
size int 文件大小
status int 文件状态标识
versionId varchar 文件版本id
isLock int 是否加锁,0和1标识
lockUserId varchar 上锁人
relatedTaskId varchar 关联任务id
createDate datetime 创建日期
updateDate datetime 更新日期
lastModifier varchar 最后一次更新人
docLevel varchar 文档密级
storePath varchar 存储真实路径
storeType varchar 存储类型,比如fastdfs

km_folder 文件夹

字段 类型 描述
id varchar 主键
name varchar 文件夹名
parentId varchar 父文件夹id
companyId varchar 公司id
folderType varchar 文件夹类型,pm、km、dl
depth int 文件夹深度
order int 文件夹同父之间的排序号
subCount int 当前层级子文件夹和文件总数
allSubCount int 下级所有文件和文件夹计数统计
creator varchar 创建者
createDate datetime 创建日期
updateDate datetime 更新日期
path varchar 在imis中文件夹规则路径
title varchar 文件标题
description varchar 描述

km_version 文件版本

字段 类型 描述
id varchar 主键
fileId varchar 文件id
folderId varchar 文件夹id
companyId varchar 公司id
name varchar 文件名
storePath varchar 存储真实路径
storeType varchar 存储类型,比如fastdfs
fileType varchar 文件类型,pm、km、dl
creator varch 创建者
size int 文件大小
createDate datetime 创建日期
updateDate datetime 更新日期

km_file_permission 文件权限

km_folder_permission 文件夹权限

字段 类型 描述
id varchar 主键
folderId varchar 文件id
companyId varchar 公司id
userId varchar 用户id
permission varchar 对文件夹拥有权限,用0,1,2标识即可
updateDate datetime 更新日期

后台业务服务及接口设计

用例过程:

    文件夹:
        新建:用户---> 新建文件夹(填写文件夹名)---> 完成
        编辑:
        删除:
    文件:
        新建:用户---> 新建文件(填写文件相关信息)--> 完成
        编辑:
        删除:
        归档:用户---> 选择需要归档文件-->选择需要归档入库的文件夹--->完成

对于文件夹存储的Path:

 整个iMIS知识管理系统是一棵树
 /imis/companyId<唯一id>
---/pm
---/pm/project/projectId<唯一id>/output/folderId
---/pm/project/projectId<唯一id>/refer/folderId
---/km
---/km/company/companyId<唯一id>/folderId
---/km/share/userId<唯一id>/folderId
---/km/user/userId<唯一id>/folderId
---/dl
---/dl/module<各模块,可定义为workrecord、workflow等>/moduleId<对于的module唯一id>/folderId

文件相关操作逻辑说明:

文件移动:文件移动时改变folderId为目标文件夹即可
文件归档:copy一份文件记录(不调用存储接口)
文件删除:
删除文件时,检测文件本身记录,如果存在storePath相同的文件则只删除 km_file 表内容,不存在则另需要调用fastdfs接口删除文件本身

后端Service主要接口:

......
//文件夹相关操作接口
    KmFolder findFolder(String folderId);

    List<KmFolder> queryFolderList(Map<String, Object> map);
    int queryFloderTotal(Map<String, Object> map);

    List<KmFolder> getFolderList();
    void saveFolder(KmFolder kmFolder);
    void updateFolder(KmFolder kmFolder);
    void deleteFolder(String folderId);

    //文件相关操作接口
    KmFile findFile(String fileId);
    List<KmFile> getFileList();
    void saveFile(KmFile kmFile);
    byte[] getFileByte(KmFile kmFile);
    void updateFile(KmFile kmFile);
    void deleteFile(String fileId);

    //文件版本操作接口
    KmVersion findFileVersion(String fileVersion);
    void saveFileVersion(KmVersion kmVersion);
    void updateFileVersion(KmVersion kmVersion);
    void deleteFileVersion(String versionId);

    //文件权限操作接口
    //文件夹权限操作接口
......
待补充

示例及相关伪代码:

相关模块设计注意事项:

项目文档设计:pm

项目文档分为产出物和参考

知识库设计:km

附件模块设计:dl

/**
     * 构建获取附件Path
     * @return string
     */
    public static  String getDlPath(String companyId,String module,String moduleId,String folderId){
        StringBuffer sb = getRootPath(companyId);
        sb.append("/" + DL);

        if(StringUtils.isNotEmpty(module) && StringUtils.isNotEmpty(moduleId) && StringUtils.isNotEmpty(folderId)){
            if(DL_MODULE_OTHER.equals(module)){
                sb.append("/" + DL_MODULE_OTHER);

            }else if(DL_MODULE_OATASK.equals(module)){
                sb.append("/" + DL_MODULE_OATASK);

            }else if(DL_MODULE_WORKRECORD.equals(module)){
                sb.append("/" + DL_MODULE_WORKRECORD);

            }else{
                sb.append("/" + DL_MODULE_OTHER);
            }
            sb.append("/" + moduleId);
            sb.append("/" + folderId);

        }else{
            return "";
        }

Files