项目:云图片

项目介绍:使用Restful风格设计HTTP服务器,提供对图片的增删改查能力,同时搭配简单的页面辅助完成图片上传和展示。

服务器API设计:资源由URI来指定,对资源的包括包括获取、创建、修改、和删除资源,通过操作资源的表现形式来操作资源

列如:http://ip:port/image?op=get&image_id=123

1.操作方法:GET查, POST增, PUT改, DELETE删
2.http path 表示操作的对象
3.补充信息一般使用body来传递,body中使用jison格式的数据来组织,方便进行调试
4.响应数据也是使用json格式来组织

数据库设计

1.创建图片表

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

,2.封装数据库接口设计

namespace image_system { 
 static MYSQL* MySQLInit() {} 
 static void MySQLRelease(MYSQL* mysql) {} 
class ImageTable { 
 ImageTable(MYSQL* mysql) { } 
 bool Insert(const Json::Value& image); 
 bool SelectAll(Json::Value* images); 
 bool SelectOne(int32_t image_id, Json::Value* image); 
 bool Delete(int image_id); 
}; 
}

服务器API设计

服务器框架

std::string StringMD5(const std::string& str); 
const std::string base_path = "./image_data/"; 
MYSQL* mysql = NULL; 
int main() { 
 using namespace httplib; 
 using namespace image_system; 
 Server server; 
 // 1. 数据库客户端初始化和释放
 mysql = MySQLInit(); 
 signal(SIGINT, [](int) { MySQLRelease(mysql); exit(0);}); 
 ImageTable image_table(mysql); 
 // 2.图片上传
 server.Post("/image_test", [](const Request& req, Response& resp) { 
 }); 
 // 3. 新增图片. 
 server.Post("/image", [&image_table](const Request& req, Response& resp) { 
 }); 
 // 4. 查看所有图片的元信息
 server.Get("/image", [&image_table](const Request& req, Response& resp) { 
 }); 
 // 5. 查看图片元信息
  // 正则表达式, \d+ 表示匹配一个数字
  server.Get(R"(/image/(\d+))", [&image_table](const Request& req, Response& resp) { 
 }); 
 // 6. 查看图片内容
 server.Get(R"(/image/show/(\d+))", [&image_table](const Request& req, Response& resp) { 
 }
); 
 // 设置静态文件目录
 server.set_base_dir("./wwwroot"); 
 server.listen("0.0.0.0", 9094); 
 return 0; 
}

1.上传图片

请求:
POST /image
Content-Type: application/x-www-form-urlencoded

[内容]

响应:
HTTP/1.1 200 OK
{
"ok": true

}

代码实现:

server.Post("/image", [&image_table](const Request& req, Response& resp) { 
 Json::FastWriter writer; 
 Json::Value resp_json; 
 LOG(INFO) << "新增图片" << std::endl; 
 // 1. 进行参数校验
 bool ret = req.has_file("filename"); 
 if (!ret) { 
 resp_json["ok"] = false; 
 resp_json["reason"] = "req has no filename field!"; 
 resp.status = 400; 
 resp.set_content(writer.write(resp_json), "application/json"); 
 return; 
 } 
 // 2. 构造 Json 格式数据, 并调用数据层接口插入数据
 const auto& file = req.get_file_value("filename"); 
 const std::string& image_body = req.body.substr(file.offset, file.length); 
 Json::Value image; 
 image["name"] = file.filename; 
 image["size"] = (int)file.length; 
 image["upload_time"] = TimeUtil::FormatTime(); 
 image["md5"] = StringMD5(image_body); 
 image["content_type"] = file.content_type; 
 // 为了防止重复, 用 md5 作为文件名
 image["path"] = base_path + file.filename; 
 ret = image_table.Insert(image); 
 if (!ret) { 
 resp_json["ok"] = false; 
 resp_json["reason"] = "insert db failed!"; 
 resp.status = 500; 
 resp.set_content(writer.write(resp_json), "application/json"); 
 return; 
 } 
 // 3. 保存文件实体
 FileUtil::WriteFile(image["path"].asString(), image_body); 
 // 4. 构造响应
 resp_json["ok"] = true; 
 resp.set_content(writer.write(resp_json), "text/html"); 
 });

2.查看所有图片信息

请求:
GET /image/


响应:
HTTP/1.1 200 OK
[
 {
        "image_id": 1,
        "image_name": "1.png",
        "content_type": "image/png",
        "md5": "[md5值]"
   }
]

server.Get("/image", [&image_table](const Request& req, Response& resp) { 
 (void) req; 
 Json::Reader reader; 
 Json::FastWriter writer; 
 Json::Value resp_json; 
 LOG(INFO) << "查看所有图片信息: " << std::endl; 
 // 1. 调用数据库接口查询数据
 Json::Value images; 
 bool ret = image_table.SelectAll(&images); 
 if (!ret) { 
 resp_json["ok"] = false; 
 resp_json["reason"] = "SelectAll failed!\n"; 
 resp.status = 500; 
 resp.set_content(writer.write(resp_json), "application/json"); 
 return; 
 } 
 // 2. 构造响应结果
 resp.set_content(writer.write(images), "application/json"); 
 return; 
 });

3.查看指定图片信息

请求: 
GET /image/:image_id 


响应: 
HTTP/1.1 200 OK 

 "image_id": 1, 
 "image_name": "1.png", 
 "content_type": "image/png", 
 "md5": "[md5值]" 

server.Get(R"(/image/(\d+))", [&image_table](const Request& req, Response& resp) { 
 Json::Reader reader; 
 Json::FastWriter writer; 
 Json::Value resp_json; 
 // 1. 获取到图片 id 
 int image_id = std::stoi(req.matches[1]); 
 LOG(INFO) << "查看图片信息: " << image_id << std::endl; 
比特科技
 // 2. 调用数据库接口查询数据
 Json::Value image; 
 bool ret = image_table.SelectOne(image_id, &image); 
 if (!ret) { 
 resp_json["ok"] = false; 
 resp_json["reason"] = "SelectOne failed!\n"; 
 resp.status = 500; 
 resp.set_content(writer.write(resp_json), "application/json"); 
 return; 
 } 
 // 3. 构造响应结果
 resp.set_content(writer.write(image), "application/json"); 
 return; 
 });

4.查看指定图片内容

请求: 
GET /image/show/:image_id 

响应: 
HTTP/1.1 200 OK 
content-type: image/png 
[响应 body 中为 图片内容 数据] 

server.Get(R"(/image/show/(\d+))", [&image_table](const Request& req, Response& resp) { 
 Json::Reader reader; 
 Json::FastWriter writer; 
 Json::Value resp_json; 
 // 1. 获取到图片 id 
 int image_id = std::stoi(req.matches[1]); 
 LOG(INFO) << "查看图片信息: " << image_id << std::endl; 
 // 2. 调用数据库接口查询数据
 Json::Value image; 
 bool ret = image_table.SelectOne(image_id, &image); 
 if (!ret) { 
 resp_json["ok"] = false; 
 resp_json["reason"] = "SelectOne failed!\n"; 
 resp.status = 500; 
 resp.set_content(writer.write(resp_json), "application/json"); 
 return; 
 } 
 std::string image_body; 
 ret = FileUtil::ReadFile(image["path"].asString(), &image_body); 
 if (!ret) { 
 resp_json["ok"] = false; 
 resp_json["reason"] = "path open failed\n"; 
 resp.status = 500; 
 resp.set_content(writer.write(resp_json), "application/json"); 
 return; 
 } 
 // 3. 构造响应结果
 resp.set_content(image_body, image["content_type"].asCString()); 
 return; 
 });

5.删除图片

DELETE /image/:image_id 

响应: 
HTTP/1.1 200 OK 

 "ok": true 

server.Delete(R"(/image/(\d+))", [&image_table](const Request& req, Response& resp) { 
 Json::Value resp_json; 
 Json::FastWriter writer; 
 // 1. 解析获取 blog_id 
 // 使用 matches[1] 就能获取到 blog_id 
 // LOG(INFO) << req.matches[0] << "," << req.matches[1] << "\n"; 
 int image_id = std::stoi(req.matches[1]); 
 LOG(INFO) << "删除指定图片: " << image_id << std::endl; 
 // 2. 调用数据库接口删除博客
 bool ret = image_table.Delete(image_id); 
 if (!ret) { 
 resp_json["ok"] = false; 
 resp_json["reason"] = "Delete failed!\n"; 
 resp.status = 500; 
 resp.set_content(writer.write(resp_json), "application/json"); 
 return; 
 } 
 // 3. 包装正确的响应
 resp_json["ok"] = true; 
 resp.set_content(writer.write(resp_json), "application/json"); 
 return; 
 });

完整代码:https://github.com/LTXER/imageservr/tree/master/image_server/server

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值