图片服务器

article/2025/10/3 0:05:14

图片服务器

图片服务器主要的功能是:上传图片,显示图片的功能
写博客的时候,插入的图片,本质上是往文章内插入一个url,图片其实是保存在在另一个服务器上,而我这个项目就是制作一个类似这样的服务器。
核心知识点
1.简单的web服务器设计开发能力(Servlet)
2.jdbc操作数据库
3.数据库设计
4.前后端交互的api的设计
5.json数据格式,使用java中的gson这个库操作json数据
6.使用html,css,javaScript构造一个简单网页。

1.数据库设计及相关操作

1.1数据库的设计

设计一个数据库用来保存图片的相关信息,这样就方便我们后续对图片的调用和存储。数据库中存储的图片的属性(元信息)图片正文,以文件的形式直接存在磁盘上的。数据库的记录一个path就对应到磁盘上的文件

元素类型说明备注
idint一张图片的id主键
imageNamevarchar(50)文件名
uploadtimelvarchar(50)下载时间
contentTypevarchar(4096)下载格式
pathvarchar(4096)文件路径
md5varchar(4096)校验和

校验和:通过一个更短的字符串,来验证整体数据的正确,短的字符串时根据原串内容根据一定的柜子来计算出来的。

1.2数据库的相关操作

我们实现对数据库的操作主要依靠JDBC编程。而其中操作的改变就是sql语句的不同,所以我们可以把其他步骤总结成方法。之后根据不同的操作进行调用就好了。
1.引入对应的依赖
2.创建数据源DataSource(指定服务器的地址,用户名,密码等)
3.和数据库建立连接DataSource.getConnection
4.拼装SQL语句
5.遍历结果集(如果是select需要,insert,update,delete不需要)
6.断开连接并回收资源。

//1.引入依赖<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.45</version></dependency>//2.创建数据源public class DBUtil {private static final String URL = "jdbc:mysql://127.0.0.1:3306/java_image_server?characterEncoding=utf8&useSSL=true";private static final String USERNAME = "root";private static final String PASSWORD = "";private static volatile DataSource dataSource = null;public static DataSource getDataSource() {// 通过这个方法来创建 DataSource 的实例if (dataSource == null) {synchronized (DBUtil.class) {if (dataSource == null) {dataSource = new MysqlDataSource();MysqlDataSource tmpDataSource = (MysqlDataSource) dataSource;tmpDataSource.setURL(URL);tmpDataSource.setUser(USERNAME);tmpDataSource.setPassword(PASSWORD);}}}return dataSource;}//3.获取连接public static Connection getConnection() {try {return getDataSource().getConnection();} catch (SQLException e) {e.printStackTrace();}return null;}
//6.关闭资源public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) {try {if (resultSet != null) {resultSet.close();}if (statement != null) {statement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}
}

为实现当操作出现问题时可以及时反馈,这里我自定义了一个异常方便预警。同时建立了一个实体类,实体类的内容与数据库的字段保持一致。

// 自定义异常:JavaImageServerException
public class JavaImageServerException extends Exception {public JavaImageServerException(String message) {super(message);}
}
// 实体类:image
import lombok.Getter;
import lombok.Setter;@Getter
@Setter
public class Image {private int imageId;private String imageName;private int size;private String uploadTime;private String contentType;private String path;private String md5;@Overridepublic String toString() {return "Image{" +"imageId=" + imageId +", imageName='" + imageName + '\'' +", size=" + size +", uploadTime='" + uploadTime + '\'' +", contentType='" + contentType + '\'' +", path='" + path + '\'' +", md5='" + md5 + '\'' +'}';}
}

1.2.1插入数据

public void insert(Image image) {// 1. 获取数据库连接Connection connection = DBUtil.getConnection();// 2. 创建并拼装 SQL 语句String sql = "insert into image_table values(null, ?, ?, ?, ?, ?, ?)";PreparedStatement statement = null;try {statement = connection.prepareStatement(sql);statement.setString(1, image.getImageName());statement.setInt(2, image.getSize());statement.setString(3, image.getUploadTime());statement.setString(4, image.getContentType());statement.setString(5, image.getPath());statement.setString(6, image.getMd5());// 3. 执行 SQL 语句int ret = statement.executeUpdate();if (ret != 1) {// 程序出现问题, 抛出一个异常throw new JavaImageServerException("插入数据库出错!");}} catch (SQLException|JavaImageServerException e) {e.printStackTrace();} finally {// 4. 关闭连接和statement对象DBUtil.close(connection, statement, null);}}

1.2.2删除数据

/*** 根据 imageId 删除指定的图片* @param imageId*/public void delete(int imageId) {// 1. 获取数据库连接Connection connection = DBUtil.getConnection();// 2. 拼装 SQL 语句String sql = "delete from image_table where imageId = ?";PreparedStatement statement = null;// 3. 执行 SQL 语句try {statement = connection.prepareStatement(sql);statement.setInt(1, imageId);int ret = statement.executeUpdate();if (ret != 1) {throw new JavaImageServerException("删除数据库操作失败");}} catch (SQLException | JavaImageServerException e) {e.printStackTrace();} finally {// 4. 关闭连接DBUtil.close(connection, statement, null);}}

1.2.3查找单张图片

/*** 根据 imageId 查找指定的图片信息* @param imageId* @return*/public Image selectOne(int imageId) {// 1. 获取数据库连接Connection connection = DBUtil.getConnection();// 2. 构造 SQL 语句String sql = "select * from image_table where imageId = ?";PreparedStatement statement = null;ResultSet resultSet = null;try {// 3. 执行 SQL 语句statement = connection.prepareStatement(sql);statement.setInt(1, imageId);resultSet = statement.executeQuery();// 4. 处理结果集if (resultSet.next()) {Image image = new Image();image.setImageId(resultSet.getInt("imageId"));image.setImageName(resultSet.getString("imageName"));image.setSize(resultSet.getInt("size"));image.setUploadTime(resultSet.getString("uploadTime"));image.setContentType(resultSet.getString("contentType"));image.setPath(resultSet.getString("path"));image.setMd5(resultSet.getString("md5"));return image;}} catch (SQLException e) {e.printStackTrace();} finally {// 5. 关闭链接DBUtil.close(connection, statement, resultSet);}return null;}

1.2.4查找全部图片

/*** 查找数据库中的所有图片的信息* @return*/public List<Image> selectAll() {List<Image> images = new ArrayList<>();// 1. 获取数据库连接Connection connection = DBUtil.getConnection();// 2. 构造 SQL 语句String sql = "select * from image_table";PreparedStatement statement = null;ResultSet resultSet = null;try {// 3. 执行 SQL 语句statement = connection.prepareStatement(sql);resultSet = statement.executeQuery();// 4. 处理结果集while (resultSet.next()) {Image image = new Image();image.setImageId(resultSet.getInt("imageId"));image.setImageName(resultSet.getString("imageName"));image.setSize(resultSet.getInt("size"));image.setUploadTime(resultSet.getString("uploadTime"));image.setContentType(resultSet.getString("contentType"));image.setPath(resultSet.getString("path"));image.setMd5(resultSet.getString("md5"));images.add(image);}return images;} catch (SQLException e) {e.printStackTrace();} finally {// 5. 关闭连接DBUtil.close(connection, statement, resultSet);}return null;}

2.基于Servlet来搭建服务器

a).Servlet运行方法。
从浏览器发送请求到tomcat上,之后根据url查找映射关系表找到对用的api类
根据对应的方法,决定给api类创建一个对象,并且调用其中的doxxx方法
执行doxxx方法tomcat构造resp对象,根据这个对象生成http响应报文,再通过socket写回给浏览器
2.服务器api设计(前后端接口设计)
a)json一种数据格式,键值对的结构,这里主要采用json格式进行信息交互
b)文件上传操作在前端如何实现(from表单)

1.新增图片

在这里插入图片描述

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1. 获取图片的属性信息, 并且存入数据库//  a) 需要创建一个 factory 对象 和 upload 对象, 这是为了获取到图片属性做的准备工作//     固定的逻辑FileItemFactory factory = new DiskFileItemFactory();ServletFileUpload upload = new ServletFileUpload(factory);// b) 通过 upload 对象进一步解析请求(解析HTTP请求中奇怪的 body 中的内容)//    FileItem 就代表一个上传的文件对象.//    理论上来说, HTTP 支持一个请求中同时上传多个文件List<FileItem> items = null;try {items = upload.parseRequest(req);} catch (FileUploadException e) {// 出现异常说明解析出错!e.printStackTrace();// 告诉客户端出现的具体的错误是啥resp.setContentType("application/json; charset=utf-8");resp.getWriter().write("{ \"ok\": false, \"reason\": \"请求解析失败\" }");return;}//  c) 把 FileItem 中的属性提取出来, 转换成 Image 对象, 才能存到数据库中//     当前只考虑一张图片的情况FileItem fileItem = items.get(0);Image image = new Image();image.setImageName(fileItem.getName());image.setSize((int)fileItem.getSize());// 手动获取一下当前日期, 并转成格式化日期, yyMMdd => 20200218SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");image.setUploadTime(simpleDateFormat.format(new Date()));image.setContentType(fileItem.getContentType());// MD5 image.setMd5(DigestUtils.md5Hex(fileItem.get()));// 利用md5是为了让文件路径能够唯一image.setPath("./image/" + image.getMd5());// 存到数据库中ImageDao imageDao = new ImageDao();// 看看数据库中是否存在相同的 MD5 值的图片, 不存在, 返回 nullImage existImage = imageDao.selectByMd5(image.getMd5());imageDao.insert(image);// 2. 获取图片的内容信息, 并且写入磁盘文件if (existImage == null) {File file = new File(image.getPath());try {fileItem.write(file);} catch (Exception e) {e.printStackTrace();resp.setContentType("application/json; charset=utf-8");resp.getWriter().write("{ \"ok\": false, \"reason\": \"写磁盘失败\" }");return;}}// 3. 给客户端返回一个结果数据//重定向,上传成功后回到主页resp.sendRedirect("index.html");}

2.查看图片信息(数据库属性)

1.查看所有图片信息

2.查看指定图片信息

在这里插入图片描述

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String imageId = req.getParameter("imageId");if (imageId == null || imageId.equals("")) {// 查看所有图片属性selectAll(req, resp);} else {// 查看指定图片selectOne(imageId, resp);}}private void selectAll(HttpServletRequest req, HttpServletResponse resp) throws IOException {resp.setContentType("application/json; charset=utf-8");// 1. 创建一个 ImageDao 对象, 并查找数据库ImageDao imageDao = new ImageDao();List<Image> images = imageDao.selectAll();// 2. 把查找到的结果转成 JSON 格式的字符串, 并且写回给 resp 对象Gson gson = new GsonBuilder().create();//    jsonData 就是一个 json 格式的字符串了, 就和之前约定的格式是一样的了.//    只要把之前的相关的字段都约定成统一的命名, 下面的操作就可以一步到位的完成整个转换String jsonData = gson.toJson(images);resp.getWriter().write(jsonData);}private void selectOne(String imageId, HttpServletResponse resp) throws IOException {resp.setContentType("application/json; charset=utf-8");// 1. 创建 ImageDao 对象ImageDao imageDao = new ImageDao();Image image = imageDao.selectOne(Integer.parseInt(imageId));// 2. 使用 gson 把查到的数据转成 json 格式, 并写回给响应对象Gson gson = new GsonBuilder().create();String jsonData = gson.toJson(image);resp.getWriter().write(jsonData);}

4.删除图片

delete/image?imageid=?

protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json; charset=utf-8");// 1. 先获取到请求中的 imageIdString imageId = req.getParameter("imageId");if (imageId == null || imageId.equals("")) {resp.setStatus(200);resp.getWriter().write("{ \"ok\": false, \"reason\": \"解析请求失败\" }");return;}// 2. 创建 ImageDao 对象, 查看到该图片对象对应的相关属性(这是为了知道这个图片对应的文件路径)ImageDao imageDao = new ImageDao();Image image = imageDao.selectOne(Integer.parseInt(imageId));if (image == null) {// 此时请求中传入的 id 在数据库中不存在.resp.setStatus(200);resp.getWriter().write("{ \"ok\": false, \"reason\": \"imageId 在数据库中不存在\" }");return;}// 3. 删除数据库中的记录imageDao.delete(Integer.parseInt(imageId));// 4. 删除本地磁盘文件File file = new File(image.getPath());file.delete();resp.setStatus(200);resp.getWriter().write("{ \"ok\": true }");}

5.查看图片具体信息

get/imageShow?imageid=?

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1. 解析出 imageIdString imageId = req.getParameter("imageId");if (imageId == null || imageId.equals("")) {resp.setContentType("application/json; charset: utf-8");resp.getWriter().write("{ \"ok\": false, \"reason\": \"imageId 解析失败\" }");return;}// 2. 根据 imageId 查找数据库, 得到对应的图片属性信息(需要知道图片存储的路径)ImageDao imageDao = new ImageDao();Image image = imageDao.selectOne(Integer.parseInt(imageId));// 3. 根据路径打开文件, 读取其中的内容, 写入到响应对象中resp.setContentType(image.getContentType());File file = new File(image.getPath());// 由于图片是二进制文件, 应该使用字节流的方式读取文件OutputStream outputStream = resp.getOutputStream();FileInputStream fileInputStream = new FileInputStream(file);byte[] buffer = new byte[1024];while (true) {int len = fileInputStream.read(buffer);if (len == -1) {// 文件读取结束break;}// 此时已经读到一部分数据, 放到 buffer 里, 把 buffer 中的内容写到响应对象中outputStream.write(buffer);}fileInputStream.close();outputStream.close();}

3.前端设计

前端主要依靠form表单进行文件的上传
我们这里采用简单的vue框架以及ajax异步请求实现对应的响应。

var app = new Vue({el: '#app',data: {author: "whggg",images: []},methods: {// GET /image,获取照片操作getImages() {$.ajax({url: "image",type: "get",context: this,success: function(data, status) {// 此处的代码在浏览器收到响应之后, 才会执行到// 参数中的 data 这就相当于收到的 HTTP 响应中的 body 部分this.images = data;$('#app').resize();}})},//删除照片操作remove(imageId) {$.ajax({url: "image?imageId=" + imageId,type: "delete",context: this,success: function(data, status) {this.getImages();// 弹出对话框alert("删除成功!");}})}}})app.getImages();

http://chatgpt.dhexx.cn/article/S1016xBy.shtml

相关文章

FastDFS搭建图片服务器

服务器规划 服务器名称IP地址和端口备注fastdfs-tracker*:22122跟踪服务器/调度服务器fastdfs-storage*:23000存储服务器 一、安装系统组件 yum install gcc -y 二、安装fastdfs 1、创建图片服务器存储目录 mkdir -p /data/image 2、下载FastDFS依赖包libfastcommon并安…

Zimg—轻量级图片服务器搭建利器

在一个互联网应用中&#xff0c;图片扮演着越来越重要的角色。有稳定的可扩展的图片存储服务器就显得尤为的重要&#xff0c;云厂商们提供了便利的图片存储服务&#xff0c;花钱就可以解决了。这里简单介绍一个开源的一个分布式图片存储服务器——zimg&#xff0c;来自己搭建一…

图片服务器的搭建

当高并发的时候容易发生图盘上传到一个服务器从另一个服务器需要读取照片 解决方法&#xff1a; 专门保存图片&#xff0c;不管是哪个服务器接收到图片&#xff0c;都把图片上传到图片服务器。 图片服务器上需要安装一个http服务器&#xff0c;可以使用tomcat、apache、ngin…

图片服务器搭建

图片服务器搭建 原先我们通过servlet上传一个用户的头像&#xff0c;需要把头像显示到网站上。就需要搭建一个图片服务器来显 示图片了。 图片服务器其实和tomcat/nginx容器的作用是一样的。目的都是要把文件从本地的磁盘上发布出去。一般常用 的图片服务器是apache服务器 &am…

三种图片服务器

2019独角兽企业重金招聘Python工程师标准>>> 到目前&#xff0c;工作中用到的图片服务器有下面三种&#xff1a; &#xff08;1&#xff09;使用Nginx搭建图片服务器 &#xff08;2&#xff09;使用阿里云图片服务器&#xff08;OOS&#xff09; &#xff08;3&…

【java】本地客户端内嵌浏览器2 - chrome/chromium/cef/jcef

目录 ★☆★ 写在前面 ★☆★★☆★ 本系列文章 ★☆★★☆★ 开源网址 ★☆★一、发现新大陆 - CEF/JCEF0、前言1、使用 jcef.jar 搭建项目2、启动包含 jcef.jar 的程序3、simple\MainFrame 注释翻译 二、定制自己的项目之 Swing1、删除导航栏2、程序启动最大化窗口&#xff0…

C#嵌入谷歌浏览器内核

1.右击项目&#xff0c;选择.net框架为4.5以上&#xff1a; 2.右击项目&#xff0c;选择“管理Nuget程序包”&#xff0c;点击“浏览”&#xff0c;搜索“CefSharp”&#xff0c;选择“CefSharp WinForms”下载安装。 安装之后到项目的引用下查看&#xff0c;会出现&#xff…

WinFrom内嵌chrome浏览器

选中项目&#xff0c;右键&#xff0c;下拉列表里选择“管理Nuget程序包&#xff08;N&#xff09;”选项&#xff0c;打开如图&#xff1a; 按照步骤装上这个nuget包&#xff0c;装上以后你的工具箱就有这个了&#xff1a; 不用拖拉控件&#xff0c;直接代码绑定把&#xff…

在网页中内嵌网页

目录&#xff1a; 文章目录 前言代码展示主页代码展示作品的代码球体运动方块旋转 结果演示 前言 在制作个人网站时&#xff0c;经常遇到一个问题&#xff0c;就是如何让自己的作品动态的显示在主页上而本文就是找到了解决办法&#xff0c;利用<embed src"xx.html&qu…

Qt实现 内嵌CEF制作浏览器(首篇)

介绍 cef支持跨平台&#xff0c;是基于Chromium的开源浏览器控件&#xff0c;全称Chromium Embedded Framework&#xff0c;因为其跨平台性&#xff0c;被广泛使用于制作浏览器。 本文主要介绍如何下载cef以及编译windows下的cef项目&#xff0c;并运行查看浏览器显示效果。 …

Qt 内嵌浏览器几种办法

1.使用axWidget QT axcontainer 然后ui里面就可以出现QAxWidget 直接拖入就可以 ui->axWidget->setControl(QString::fromUtf8("{8856F961-340A-11D0-A96B-00C04FD705A2}")); ui->axWidget->setFocusPolicy(Qt::StrongFocus); ui->axWidget…

CEF内嵌浏览器 编译

CEF github 笔记 https://github.com/fanfeilong/cefutil/blob/master/doc/CEF%20General%20Usage-zh-cn.md#using-binray 介绍 CEF全称Chromium Embedded Framework&#xff0c;是一个基于Google Chromium 的开源项目。Google Chromium项目主要是为Google Chrome应用开发的…

Unity内嵌浏览器插件(Android、iOS、Windows)

文章目录 一. Embedded Browser插件下载2. 使用 二. UniWebView插件1. 下载2. 使用 三、我自制的迷你浏览器 一. Embedded Browser插件 下载 平台&#xff1a;Windows 链接&#xff1a;https://pan.baidu.com/s/1h2oyGW6FsvPlOGCob0VrfA 提取码&#xff1a;02tu 2. 使用 导…

QT内嵌浏览器与JS通讯

QT内嵌浏览器与JS通讯 1. 概述2. JS调用QT方法2.1 QT代码2.2 HTML/代码 3 WebEngineView示例4. 效果展示 1. 概述 QT内嵌浏览器支持拦截请求、获取cookie、js代码注入及js调用QT方法。本篇主要介绍js调用QT方法其他方式的使用QT WebEngineView 拦截请求、获取cookie&#xff0…

Unity 工具之 内嵌网页/浏览器 web view / browser 插件的整理大全(包括Window Mac Android iOS 等)

Unity 工具之 内嵌网页/浏览器 web view / browser 插件的整理大全&#xff08;包括Window Mac Android iOS 等&#xff09; 目录 Unity 工具之 内嵌网页/浏览器 web view / browser 插件的整理大全&#xff08;包括Window Mac Android iOS 等&#xff09; 一、简单介绍 二、…

Unity 工具之 内嵌网页/浏览器插件使用和学习笔记

1、Embedded Browser 插件&#xff08;文件夹名ZFBrowserUnity&#xff09; 优点&#xff1a;设置简单&#xff0c;功能强大&#xff1a;输入url地址&#xff0c;拉取网页信息&#xff0c;可设置页面尺寸&#xff0c;可显示透明背景的网页&#xff0c;可与显示的页面进行互动&…

java内嵌浏览器的几种方式

最近遇到一个特殊的项目需求&#xff0c;就是需要在一个屏幕上打开多个窗口大小不同的浏览器、并且显示不同的页面。因为是需要浏览器无边框的&#xff0c;在网上找了好多资料&#xff0c;发现前端好像很难实现。所以就打算采用java后台内嵌浏览器&#xff0c;然后实现无边框的…

winform内嵌浏览器的2种实现方式

可使用WebBrowser或axWebBrowser实现winform窗体内嵌浏览器 一 使用axWebBrowser打开浏览器 1.新建个winform项目 2.添加axWebBrowser控件 打开工具箱,右键空白处,点击选择项 选择COM组件,勾上Microsoft Web Browser 把控件拉拽到winform窗体上 3.使用axWebBrowser打开浏览器 …

云表中表单配置内嵌浏览器

给大家分享一个在表单里也能嵌入网页的一个功能&#xff0c;云表的内嵌浏览器 1.首先我们先添加一个云表内嵌浏览器&#xff0c;在模板设计的右边点击表格面板点击下拉后可以先将浏览器&#xff0c;这个浏览器是需要一整个表格的 2.添加好浏览器后&#xff0c;我们表单设置…

Android开发实用小技巧九——内嵌WebView的使用(内置浏览器)

文章目录 前言一、效果展示二、代码1.样式布局2.活动页面 总结 前言 内嵌WebView的使用&#xff08;内置浏览器&#xff09;。 一、效果展示 二、代码 1.样式布局 res/layout/activity_browser.xml &#xff1a; <?xml version"1.0" encoding"utf-8"…