业务需求
- 中介从业用户发布二手房房源信息,要求能够上传房源图片,房源图片控制在8张。
- 发布过程中,为了避免用户使用失误,要求房源图片上传后且在房源其他信息尚未提交前,就算不小心刷新页面,上传的图片信息也要能够保留。
- 图片上传后要能够立刻在页面上显示缩略图效果。
需求分析
针对图像文件,我们一般是将其保存在服务器的硬盘中,而非存储到数据库中,仅仅只是把文件的路径保存到数据库中,需要时,再查询后调用即可。所以我们需要设计一张表,用来放图片的基本信息。
一个房源一般是可以拥有多张图片,同时依据实际业务的限定来说,一张图片正常也只能对应一个房源(避免假房源),所以我们在设计数据库表示,房源与图片应该是一对多的关系。而我们的产品需求面向的是二手房经纪人,一个房源信息在网站上肯定是会重复的,房源与用户的对应关系是多对多的关系。所以为了方便用户管理图片,我们图片资源表也应该与用户建立联系,用户与图片资源的对应关系也应该是一对多的关系。
正常在网页中,我们都会在同一个页面中完成基本信息和图片上传的任务,但是但是图片上传一般情况是在<input type="file">控件添加文件后,在整个大的表单提交前,就先把图片上传到服务器做处理,所以头像上传是先做的,然后再做普通信息的提交。
这就有一个问题了:这两个操作是分步进行的,那如何能够将两部分的信息关联起来,并且还要预防中间出现的任何意外状况,比如:
- 上传了图片,结果房源中途因其他原因不发布了或以后再发布,这种情况一旦多了,势必造成很多垃圾资源的堆积。
- 图片上传之后,网页卡死,不得不刷新页面,刷新后无法获取已经上传的图片信息,导致用户体验下降。
- 图片是优先上传的,这意味着房源信息还没建立,自然数据库中房屋ID还没有,那要如何建立图片与房源之间的关联?
功能设计
为了解决一系列的问题,我们可以这么做:
- 首先:图片上传时,当上传成功后,随即将图片信息写入数据库,数据库结构如下图:
其中用户ID和房屋ID分别与用户表和房屋信息表建立外键约束(当然其实只要逻辑有控制,数据库中不建立也无妨),房屋ID设置为非必输。当我们上传图片时,因为房屋信息还没有建立,所以此刻我们根本是无法获取房屋ID,但是我们可以获取得到用户ID,这样可以先让我们的图片资源,与用户先做一个关联,这样做关联的好处在于后续我可以对房源信息表单提交时,校验一下用户ID,确保不会出现一些漏洞或风险(篡改他人数据)。- 其次:写入数据库成功后,将写入的数据都装入List集合当中,通过Ajax返回前端,然后刷新页面,并且将IMAGE_ID设置到<img>的alt属性当中,把IMAGE_SRC设置到src属性当中,这样就可以把缩略图显示出来了。当然这只是一种办法,我们可以创建一组<input type="hidden">的控件来暂时储存这些数据。用于后续表单提交时,一并再传到后端。
- 当房源信息表单提交后,后端先将房源信息写入数据库,然后再校验刚才的那些图片信息是否与当前操作的用户ID相同,验证通过后,就可以插入HOUSE_ID到图片信息表当中了。
- 这样就建立了完整的图片与表单分部上传的机制,保证了信息的完整性和真实性。最重要是能够保证图片资源与房屋资源能够正确的建立起关联。
- 回顾我们其实还有一点需求没有达成,就是当用户上传后图片结果中断了房源发布,那怎么办呢?其实办法很简单,这只需要通过设置定时任务,比如在夜间跑批的时候,统一的查询数据库中,没有HOUSE_ID的图片信息,既不完整的图片信息,然后就可以根据查询出来的SRC地址,转换成本地硬盘目录,然后再删除它们,删除的方法也有分两种,一种是直接在JAVA中删除文件,还有一种是将文件的路径都保存下来然后写入一个文本当中,接着调用本地命令或脚本,一并删除。我个人比较倾向于后者,我是直觉认为这样效率可能会高一点,但没有做过测试,有兴趣的朋友可以试试。