这是在工作中遇到的问题,首先介绍一下我使用的场景:
数据表:
sys_article -- 存放文章标题、作者等等基础信息
sys_article_detail -- 存放较为复杂的富文本内容信息(用 content 字段存储),用 article_id 外键与文章关联,一对一
sys_annex -- 存放公共的附件信息,包括附件基本信息,以及远程服务器地址,用 obj 和 obj_id
图片与文章的关联,分为两种:
一是文章封面,obj为article,obj_id为文章id,type为cover;
二是文章富文本内容中的图片或者附件,obj也为article,obj_id为文章id,type为content
以下是我用到的三张表结构:
CREATE TABLE `sys_article` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ‘主键‘, `title` varchar(100) DEFAULT ‘‘ COMMENT ‘标题‘, `author` varchar(50) DEFAULT NULL COMMENT ‘作者‘, `categary` varchar(255) DEFAULT NULL COMMENT ‘类型‘, `sort` int(11) DEFAULT ‘0‘ COMMENT ‘排序值‘, `is_top` int(11) DEFAULT ‘0‘ COMMENT ‘是否置顶(0 置顶,1 不置顶)‘, `status` char(1) DEFAULT ‘0‘ COMMENT ‘状态(0 发布,1 未发布)‘, `read_num` int(11) DEFAULT ‘0‘ COMMENT ‘点击量/阅读量‘, `create_by` varchar(50) DEFAULT NULL COMMENT ‘新增人‘, `create_time` datetime DEFAULT NULL COMMENT ‘新增时间‘, `update_by` varchar(50) DEFAULT NULL COMMENT ‘修改人‘, `update_time` datetime DEFAULT NULL COMMENT ‘修改时间‘, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COMMENT=‘文章‘; CREATE TABLE `sys_article_detail` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ‘主键‘, `article_id` int(11) DEFAULT NULL COMMENT ‘文章id‘, `content` text COMMENT ‘文章内容(富文本)‘, `create_by` varchar(50) DEFAULT NULL COMMENT ‘添加人‘, `create_time` datetime DEFAULT NULL COMMENT ‘添加时间‘, `update_by` varchar(50) DEFAULT NULL COMMENT ‘修改人‘, `update_time` datetime DEFAULT NULL COMMENT ‘修改时间‘, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COMMENT=‘文章详情‘; CREATE TABLE `sys_annex` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT ‘ID‘, `obj` varchar(255) DEFAULT NULL COMMENT ‘对象名称‘, `obj_id` bigint(20) DEFAULT NULL COMMENT ‘对象id‘, `type` varchar(255) DEFAULT NULL COMMENT ‘附件类型‘, `size` bigint(20) DEFAULT NULL COMMENT ‘附件大小‘, `ext` varchar(255) DEFAULT NULL COMMENT ‘扩展名‘, `name` varchar(500) DEFAULT NULL COMMENT ‘文件名称‘, `path` varchar(500) DEFAULT NULL COMMENT ‘路径‘, `sort` int(11) DEFAULT ‘0‘ COMMENT ‘排序‘, `introduce` varchar(500) DEFAULT NULL COMMENT ‘介绍‘, `group_name` varchar(255) DEFAULT NULL COMMENT ‘附件服务器分组‘, `remote_file_name` varchar(255) DEFAULT NULL, `start_date` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT ‘有效时间起‘, `end_date` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT ‘有效时间止‘, `create_by` varchar(64) DEFAULT NULL COMMENT ‘创建者‘, `create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT ‘创建时间‘, `update_by` varchar(64) DEFAULT NULL COMMENT ‘更新者‘, `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT ‘更新时间‘, `remark` varchar(500) DEFAULT NULL COMMENT ‘备注‘, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=75 DEFAULT CHARSET=utf8mb4 COMMENT=‘公共文件信息表‘;
语言和框架:
我采用的是 java Spring boot框架
文件管理插件:
我使用的是FastDFS插件对文件服务器中的文件进行管理
前端富文本编辑器:
我采用vue的 quil-editor 编辑器
增删改查流程:
新增:
前端需要准备的数据有:
articleForm = {
title: ‘‘,
author: ‘‘,
sort: 0,
isTop: ‘1‘,
status: ‘0‘,
content: ‘‘,
}
其中,需要强调一下:
1. content是富文本框的内容,富文本框中可以对字体样式、对齐方式等进行调整,做了应的调整之后,在对应行的p标签中就会被加上对应的样式类,如果插入图片,我们需要自定义插入图片的函数逻辑,通常是指向一个上传的接口,然后上传成功,返回图片的服务器,在光标对应的位置插入一个img元素,并把图片的url赋值给它的src属性,这样就完成了图片的插入。
2. 在后端的图片上传接口中,我们接收到图片的文件对象后,从中读取对应的文件流和文件信息,然后传到配置好的文件服务器,并把文件信息封装成 sys_annex 对象,暂存到sys_annex这一张表中,并返回文件地址给前端。需要注意的是,此处由于文章并没有新增提交,我们并没有办法拿到文章的id,需要等到文章新增成功后,再来更改文章id较为合适(由于图片的地址也是唯一的,我们可以通过取出富文本中的图片地址来查询和修改 sys_annex)
后端新增流程:
首先,我们在后端用了一个 SysArticleRequest 对象来存储请求的参数,然后我们把对象中的属性取出,封装成sysArticle和sysArticleDetail对象,先插入sysArticle取得自增长id,再插入sysArticleDetail,然后还有对富文本内容content进行解析,取出其中所有的图片地址,去查询到对应的sysAnnex对象集合,把它们的obj改成article,obj_id改成文章id,然后返回结果给前端,插入差不多就完成了
删除:
前端需要准备的数据:文章id或者文章id集合(对应单个删除和批量删除,根据实际需要自定义)
后端删除流程:
首先,根据id取到sysAnnex集合,遍历,删除远程服务器的文件,然后删除sys_annex记录(包括文章封面
和富文本中的图片)
然后删除 sys_article_detail的记录
最后删除 sys_article记录,然后返回结果给前端
编辑:
涉及到富文本内容,编辑相对来说是比较复杂的
前端需要准备的数据有:
articleForm = {
title: ‘‘,
author: ‘‘,
sort: 0,
isTop: ‘1‘,
status: ‘0‘,
content: ‘‘,
oloContent: ‘‘,
}
跟新增比起来,我们需要多准备一个oldContent字段,表示修改之前的内容,该字段需要在编辑页面刚加载数据回显的时候就赋值
除了普通的字段外,封面图片也需要注意,上传是手动的,提交时才会上传,而删除是直接删除的,后端直接删除sys_annex和对应的服务器文件
后端修改流程:
我们同样用SysArticleRequest进行修改数据的传输,同样的,把把对象中的属性取出,封装成sysArticle和sysArticleDetail对象,首先根据文章id修改sys_article_detail,再修改sys_article。
此处需要注意的是,我们还有一个 oloContent 字段,我们需要分别将content和oldContent中的图片地址取出来,遍历两个集合,找出原来有但现在没有的图片地址,存入一个集合,然后根据这个集合的地址,查到sys_annex集合,并删除它们和对应的文件,返回结果给前端;同样的,对于富文本中新增的图片,我们需要把它们的obj改成article,obj_id改成文章id,如此,我们的修改流程才算走完了
查询:
查询主要涉及到 文章关联文章内容以及文章封面的查询,这里就不多强调了
流程中存在的问题:
1.由于富文本涉及到文件上传,我们如果没有设置一个临时路径,用于存储还未保存的富文本中的图片,这样,假设我们在新增或编辑时点击保存,或者遇到意外关闭网页,那我们上传的图片会成为远程文件服务器中的垃圾文件
2.基于第一个问题,如果我们设置了临时路径,那么当实际开发中,我们使用nginx的负载均衡,把程序部署在多台物理机上,由于 nginx 代理多服务器的轮询机制,我们如果把临时路径放在应用服务器上,那么我们可能上传了文件在这台服务器的临时路径,而新增的时候去另外一台取,会存在取不到文件的问题
3.综上所述,我们可以在文件服务器中,建立一个专门存储临时文件的路径,然后将所有临时文件放到这里来,这样就不存在存取不在一台服务器上的问题。
4.无论是在哪里设置临时文件路径,我们都需要定时去清除这些临时文件,可以在程序中写一个定时任务,执行每隔一段时间(比如一周)就会去清理文件服务器中的临时文件。
原文地址:https://www.cnblogs.com/winkcheng/p/12426424.html