项目简介
解决GitHub、博客中插入图片的问题;给定一个url,能够获得图片内容
项目功能
一个HTTP服务器,提供对图片的增删改查功能,同时能够完成上传图片,展示图片。
项目页面展示
选择图片界面
展示图片界面
删除图片界面
查看图片内容界面
数据库设计
设计一张图片表
MySQL脚本
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 '图片所在路径')
接口设计
下载一个前端代码和文档,根据前端分析来写后端业务
新增图片
根据前端代码,新增接口url为image,重写的是doPost方法
1.解析请求数据,获取图片的每个属性
2.根据md5校验码,验证是否上传过该图片
//获取part(上传图片文件)的输入流
InputStream is = p.getInputStream();//获取上传文件的输入流(数据)
//根据输入流转md5校验码
String md5 = DigestUtils.md5Hex(is);
//如果已上传该图片(相同的md5),就不能插入数据和保存本地
int num = ImageDAO.queryCount(md5);
if(num >= 1){
throw new AppException("上传图片重复");
}
3.将上传图片保存到本地路径
p.write(IMAGE_DIR+"/"+md5);
4.将图片信息保存到数据库
Image image = new Image();
image.setImageName(name);
image.setContentType(contentType);
image.setSize(size);
image.setUploadTime(uploadTime);
image.setMd5(md5);
image.setPath("/"+md5);
int n = ImageDAO.insert(image);
查看所有图片元信息、查看指定图片元信息
这两个接口都是重写doGet方法,查看指定图片信息需要传参数,所以我们可以设计到一个方法中,根据有无参数来判断是查看所有图片还是指定图片
String id = req.getParameter("imageId");
Object o = null;
//查询所有图片: o=List<Image>
if(id == null){
o = ImageDAO.queryAll();
}else{//查询指定id的一个图片: o=image对象
o = ImageDAO.queryOne(Integer.parseInt(id));
}
查看图片内容
1.首先要设置响应返回的数据类型要和图片类型保持一致
2.因为图片内容是以二进制方式存储的,所以使用一个字节数组。输入流读出到数组中,输出流再写入
3.一定要刷新,并且关闭输入流、输出流,否则会出现缓冲或者读取不到的问题。
String id = req.getParameter("imageId");
Image image=ImageDAO.queryOne(Integer.parseInt(id));
resp.setContentType(image.getContentType());
String path = ImageServlet.IMAGE_DIR + image.getPath();
FileInputStream fis = new FileInputStream(path);
OutputStream os = resp.getOutputStream();
byte[] bytes = new byte[1024*8];
int len;
while((len=fis.read(bytes)) != -1){
os.write(bytes, 0, len);
}
os.flush();
fis.close();
os.close();
扩展功能:基于白名单方式的防盗链(简单方法)
通过 HTTP 请求头中的 Referer字段判定是否是指定网站请求图片.
1.使用HashSet来存储(有唯一性)
private static final Set<String> whiteList = new HashSet<>();
static {
whiteList.add("http://localhost:8082/java_image_server/");
whiteList.add("http://localhost:8082/java_image_server/index.html");
}
2.在方法中添加一处判断
String referer = req.getHeader("Referer");
if(!whiteList.contains(referer)){//白名单不包含当前请求的Referer,不允许访问
resp.setStatus(403);
//还可以设置响应体数据
return;
}
删除图片接口
重写doDelete方法
1.数据库根据id删除图片数据
2.本地磁盘删除图片(在数据库删除之前,先获取图片路径)
本地删除图片使用File
File f = new File(path);
f.delete();