项目:图片服务器(图床)
一:项目背景:
我们平常写博客或者github,本质上是往文章中放了一个url ,这个链接对应的资源在另一个服务器上。而我们这个项目就是实现这样一个服务器,可以存储和展示我们的珍贵相片。
二:开发环境:
- 操作系统:windows10
- 开发工具:IDEA专业版
- web服务器:Tomcat 8.5.51
- JDK: java 1.8
三:图片功能:
服务器有上传图片,展示图片,删除图片,查询图片,并且实现一个简单的前端网页去呈现我们这些操作。
四:技术亮点:
- 使用HttpServlet类并覆写其中的一些方法,实现服务器端根据请求计算生成响应的过程
- 2.MySQL存储上传的图片,及图片各属性。(简单,容易上手)
文件上传---使用第三方依赖commons-fileupload(这个库为我们封装了一些上传文件所需要的类,方法) 3.MD5:校验和,通过图片内容hash出一串数字串。我们可以通过一个短的字符串来验证整体数据的正确性。
选用MD5的原因:
- 原 来字符串的长度不回影响最终MD5的值,MD5是一个定长32长(16进制)。而 且 原字符串一点点的改动就会导致MD5变化很大。
- 两个相同内容的字符计算出的MD5一定是一样的。
- 两个一样的MD5值大概率下原字符串是一样的。根据这个特点我们可以对图片的内 容 进行加密,然后判断变化之后的字符串是否相等,如果相等,说明有重复的图片,那 我们只需在磁盘中存储一份,优化磁盘存储空间。
- 4 . json数据传输----Gson第三方库
我们的请求和响应都是以json格式进行解析和生成响应。 - 5.前后端交互-----Ajax异步提交
异步提交可以局部刷新页面,可以减轻服务器的负担。
异步提交,通过jQuery实现非常方便。五:数据库设计:
我们要实现图片服务器,必须有存储图片的列表。
图片表的属性如下:
属性解释:
imgeId:图片存入数据的自增主键
imageName:图片的名字
size:图片的大小
uploadTime:图片的上传时间,格式为(yyyyMMdd)
contentType:图片类型,image/jpeg,如果不是图片类型则不上传。
path:磁盘的相对存储路径。图片的内容是存储在硬盘上。
md5:根据图片内容计算MD5,如果上传的两张图片内容一样,那么在硬盘中只存储一份即可。
六:图片的具体实现细节:
上传图片:我们利用form表单提交数据实现的。
注意:type=file.表示上传文件
enctype=multipart/form-data,否则提交不了二进制数据的,图片内容是以二进制形式存储。
method=post 请求方法是post,因为post方法带请求体。后端代码:利用fileupload拿到文件对象FileItem的集合。我们这里只上传一个文件。根据FileItem对象,我们可以获取上传上来的文件的大小,格式等数据。我们将这些数据和自己设置的图片存储路径封装为一个Image对象将该对象存入数据库。之后再创建一个File对象,将图片的二进制内容写入磁盘。
- 删除图片
1.删除图片是根据用户传来的参数imageId来进行选定的,找出数据库中符合imageId的图片,删除数据库存储。
2.根据imageId封装Image对象,再根据image对象删除磁盘存储。 - 展示图片:
1.前端代码利用一个Vue对象的data属性存储一个images集合(这里存储的是从后台查询到的图片的集合)。通过V-for遍历images集合,每一个image发起一个Ajax异步请求去请求展示图片的servlet.
2.后台的servlet根据前端传来的imageId查询到指定图片,根据图片属性(path)去找到磁盘中的图片内容(二进制形式存储),再以字节流的方式传回前端展示。
3.以流的方式写回的时候,指定图片的格式为数据库中记录的格式。七:效果展示:
首先展示已经存在数据库的图片:
上传一张新图:
1.点击上传按钮,选择图片
2.点击“打开”,进入到此页面
3.点击提交按钮,相册中新增一张图片
删除图片功能:
选择一张图片,点击“删除”按钮
弹出alart(),确认删除操作,请点击“确认”
返回到首页,返现图片删除成功
查看图片属性功能:查看数据库中已有的所有图片属性:
查看图片属性功能:根据id查看指定图片属性:
七:项目亮点:
一:简单的防盗链机制****
我的服务器链接可能会被其他人使用,如果请求服务器的人数过多,会导致服务器崩溃。
解决方法:请求中加一个referer字段,如果这个referer在我的白名单中,就允许访问。
白名单:hashset中添入允许的referer字段,展示图片的时候只需判断一下当前的referer是否再我的hashset中,
referer:表示当前请求的上个页面的地址。
二:优化磁盘存储空间****
如果两个图片的内容一样,就在磁盘上只存储一份文件即可。
通过计算MD5来判断两个图片的内容是否一样。
实现思路:
上传图片的时候,先判定新图片的MD5值(数据库的一个字段)在数据库中是否存在。如果存在,就不把内容写到磁盘上;如果不存在,再写磁盘文件。
1)修改上传带码的逻辑。磁盘文件名用MD5值表示。
2)修改ImageDao,新增一个接口,能够按照MD5值查找数据库内容。
3)修改上传代码的逻辑,根据MD5值判定,当前图片是否要写磁盘。
八:过程中遇到的问题:
1.HTML文件Vue对象的methods属性拼写有误,导致其中的app.getImages()不能被识别;(由此可见,这种细节性错误一定要认真,很难再次察觉)
2.因为我的dao层连接数据库的ip和port为远端不在本地,导致数据库连接失败,前端网页也因此加载不出来。(我们建议数据连接本地主机就行,连接远端需要权限设置,比较麻烦)
服务器端代码没有和数据连接成功,导致上传照片出现500.
还有,连接port时候记得该端口的安全组一定要打开,否则也是连接不上的。(如图示)
经过一番折腾,数据库终于连接成功,前端加载很成功。