图片服务器项目

项目简介

图片服务器:解决项目中插入图片的问题

实现功能

核心就是一个 HTTP 服务器, 提供对图片的增删改查能力,同时搭配简单的页面辅助完成图片上传和展示

应用知识点

Web项目的设计能力,Servlet的使用
MySQL数据库的设计和使用
基于 md5 实现相同图片内容只存一份
基于白名单方式的防盗链

项目的搭建

数据库设计

drop database if exists image_system;
create database image_system character set utf8mb4;
use image_system;

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 '图片所在路径')

实现后端

创建ImageServlet类

这个类的 doPost 对应插入图片, doGet 对应查看图片信息, doDelete 对应删除图片

插入图片
getImages() {
                $.ajax({
                    url: "image",
                    type: "get",
                    context: this,
                    success: function(data, status) {
                        this.images = data;
                        $("#app").resize();
                    }
                })
            }

根据前端代码,新增接口url为image,重写的是doPost方法
1.解析请求数据,获取图片的每个属性
2.根据md5校验码,验证是否上传过该图片

//1. 解析请求数据(part类接收)
//因为前端的数据类型时multipart/form-data(文件上传,上传的文件可以是任意的类型)  所以不能用之前的接收方式来接受前端给到的数据了,只能用getPart的方式接收前端的数据
 Part p = req.getPart("uploadImage");
 long size = p.getSize();//获取上传的文件大小
 String contentType = p.getContentType();//获取每个part的数据格式
 String name = p.getSubmittedFileName();//获取上传的文件

//图片上传时间,数据库是保存的字符串 用日期格式化的类来转换
Date date = new Date();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String uploadTime = df.format(date);

//获取part(上传图片文件)的输入流
InputStream is = p.getInputStream();//获取上传文件的输入流(数据)
//根据输入流转换为md5校验码
String md5 = DigestUtils.md5Hex(is);

//如何判断 图片已上传 若相同的MD5值 就不能插入数据和保存本
 int num = ImageDao.queryCount(md5);
 if (num>= 1){
    throw  new AppException("上传图片重复");
    }

注意:
在这里插入图片描述
3,将上传图片把保存至本地路径,将图片信息保存至数据库

 //2-1: 保存上传图片为服务端本地文件
//上传的图片名可能重复,但Md5是唯一的
p.write(IMAGE_DIR+"/"+md5); //p.write("E://TMP");//保存文件到服务器本地某个路径
//2-2: 图片信息保存在数据库---->后续查询图片列表接口要用
//插入数据操作,字段太多,最好把字段转换为对象的属性
Image image = new Image
image.setImageName(name);
image.setContentType(contentType);
image.setSize(size);
image.setUpload_time(uploadTime);
image.setMd5(md5);
image.setPath("/"+md5);
int n = ImageDao.insert(image);
查看图片信息
 req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("application/json");

        //1.解析请求数据
        String id = req.getParameter("imageId");
        Object o= null;

        if ( id == null){
            //查询所有图片 o= list<image>
            //List<Image> list = ImageDao.queryALL();
            o = ImageDao.queryALL();
        }else {
            //查询指定ID的一个图片 o = image对象
            //Image image = ImageDao.queryOne(Integer.parseInt(id));
            o = ImageDao.queryOne(Integer.parseInt(id));
        }
        //把对象 序列化为字符串
        String json = util.serialize(o);
        resp.getWriter().println(json);
删除图片
 req.setCharacterEncoding("UTF-8");
        resp.setContentType("application/json");
        resp.setCharacterEncoding("UTF-8");

        String id = req.getParameter("imageId");
        //数据库根据ID删除图片数据
        Image image = ImageDao.queryOne(Integer.parseInt(id));
        int n = ImageDao.delete(Integer.parseInt(id));
        //本地硬盘删除图片文件
        String  path = IMAGE_DIR+image.getPath();
        File f = new File(path);
        f.delete();
        ok(resp);

创建imageshow类

获取图片内容
//1.解析请求数据 imageId
  String id = req.getParameter("imageId");
 //2.业务处理 2.1根据ID查询图片path字段 2.2通过path找本地图片
  Image image = ImageDao.queryOne(Integer.parseInt(id));
//图片是以二进制数据放在body 同时要指定connectType
resp.setContentType(image.getContentType());
//本地图片的绝对路径
String path = ImageServlet.IMAGE_DIR + image.getPath();
//io输入流读文件
FileInputStream fis = new FileInputStream(path);

 //3.返回响应 服务器本地图片的二进制数据
 OutputStream os = resp.getOutputStream();
 //输出流都是输出到body
  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 中的 refer 字段判定是否是指定网站请求图片
1.先构建一个hashset的白名单

private static final Set<String> whiteList = new HashSet<>();
    static {
        //白名单允许获取图片内容
        whiteList.add("http://localhost:8083/java_image_server/index.html");
        whiteList.add("http://localhost:8083/java_image_server/");
    }

2.在方法中进行修改

 String referer = req.getHeader("Referer");
        if (!whiteList.contains(referer)){
            //白名单里面不包含当前请求的Referer 不允许访问 返回一个403(登录了没有身份权限)401(没有登录,没有访问权限)
            resp.setStatus(403);
            return;//后续代码不执行了
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值