图片服务器测试用例
图片上传服务器系统说明
数据库设计
drop database if exists drawing_bed;
create database drawing_bed character set utf8mb4;
use drawing_bed;
drop table if exists image_table;
create table image_table(image_id int not null primary key auto_increment,
image_name varchar(50),
size bigint,
upload_time varchar(50),
md5 varchar(128),
content_type varchar(50) comment ‘图片类型’,
path varchar(1024) comment ‘图片所在路径’);
服务器 API 设计
新增图片
写一个简单的 html 来上传图片,因为需要上传的是图片,而不是简单地数据,所以不使用浏览器默认的application/x-www-form-urlencoded格式和常见的application/json,而使用multipart/form-data。
我们使用表单上传文件时,必须让 表单的 enctype 等于 multipart/form-data。
文件上传:
设定接口如下.
请求
POST /image
Content-Type: application/x-www-form-urlencoded
------WebKitFormBoundary5muoelvEmAAVUyQB
Content-Disposition: form-data;
name=“uploadImage”; uploadImage=“图标.jpg” Content-Type: image/jpg
…[图片正文]…
响应:
HTTP/1.1 200 OK
{
“ok”: true,
}
查看所有图片元信息
请求:
GET /image
HTTP/1.1 200 OK
[
{
“imageId”: 1,
“imageName”: “1.png”,
“contentType”: “image/png”,
“md5”: “[md5值]”
}
]
删除图片
请求:
DELETE /image?imageId=1
响应:
HTTP/1.1 200 OK
{
“ok”: true
}
查看图片内容
请求:
GET /imageShow?imageId=1
响应:
HTTP/1.1 200 OK
content-type: image/png
[响应 body 中为 图片内容 数据]
前端
前端使用了一点Vue.js的知识
整体流程
第一步:输入index.html,页面进行初始化调用getImages()函数,去请求后端全部图片的信息
第二步:调用后端image路径下的doGet()方法,将相应的结果返回给前端
第三步:上传图片,调用后端image里的doPost()方法,将图片保存在服务器的本地文件中,添加后前端重新调用getImages()函数,显示所有图片
第四步:删除图片,调用后端image路径下的doDelete()方法,删除后前端重新调用getImages()函数,显示所有图片
基于白名单方式的防盗链
通过 HTTP 中的 refer 字段判定是否是指定网站请求图片.
修改 ImageShowServlet.doGet 方法
基于 MD5 实现相同内容图片只存一份
使用的是DigestUtils.md5Hex(inputStream)这个函数
整体思路
先获取到上传文件的输入流(二进制数据)
再根据输入流计算mid字符串(不同的数据mid不同)
在将图片保存到数据库和服务器本地文件之前先判断数据库中是已经 有相同的MD5了,如果有则禁止插入,如果没有才进行下面的代码
然后将图片保存到服务器本地(使用MD5 + 相对路径)
最后将图片保存到数据库当中
基于Filter的过滤器
LoginFilter有三个方法,我们只需要重写doFilter()即可
琐碎的知识点
保证当照片名称相同,但内容不同时,在服务器保存的文件名也是唯一的 而不能用前端传来的name(所以使用了路径+MD5的方式)
保存在数据库中的路径建议写成第二种要是在本地将文件名移动或者改名了要是在本地将文件名移动或者改名了,直接修改后端代码的IMAGE_PATH
不过在取图片的时候要补全路径
将文件写到服务器本地时,需要先从part中获取输入流,在直接用函数part.write将文件写入到服务器本地
要想取图片的话,并显示到网页上。先从服务端本地取得输入流,在将输出流输出到resp里(servlet的相应可以是任意格式的(html、文件)) 可能一次没读满(所以int len = fileInputStream.read(bytes) != -1)
结束完一定要关闭io流,防止被占用而在服务端本地删不掉
删除数据库当中的文件后,需要删除服务器的本地文件,本地的文件,在Java中的一个对象,可以操作这个文件
但在删除文件的时候,有可能数据库中删除文件了,但是服务器本地删除文件出错,所以需要将两个删除用事务绑定在一起,保证事务的四大特性
基于防盗链的方式过滤器----Filter,实现Filter接口,重写init,doFilter,destory方法
先获取到,应用上下文的服务路径
先获取到,应用上下文的服务路径,String url = req.getServletPath()
拦截敏感资源,前端的话,重定向到login.html,后端敏感资源的话返回401状态码,并返回相应的json数据,如果访问开放的资源,或者已登录访问敏感资源,则运行执行chain.doFilter()方法
使用Referce防盗链的方式,来防止别人下载,但是可以使用postman来设置header来时模拟登陆,不安全需要使用其他方法