• C++文件服务器项目—数据库表设计 与 后端接口设计—6


    前言

      到本文为止,该项目的前置知识已经写的差不多了。本文规划了数据库表的设计 和 后端与前端接口的设计,接下来就可以编写fastcgi程序进行运行了。项目以及项目相关源码地址:gopherWxf git

      本专栏知识点是通过零声教育的线上课学习,进行梳理总结写下文章,对c/c++linux课程感兴趣的读者,可以点击链接 C/C++后台高级服务器课程介绍 详细查看课程的服务。

    1. 数据库建表

    在这里插入图片描述

    1.1 用户信息表 user_info

    字段解释
    id用户序号,自动递增,主键
    user_name用户名字
    nick_name用户昵称
    password密码
    phone手机号码
    email邮箱
    create_time注册时间
    CREATE TABLE `user_info`
    (
        `id`          bigint(20)                        NOT NULL AUTO_INCREMENT COMMENT '用户序号,自动递增,主键',
        `user_name`   varchar(32)                       NOT NULL DEFAULT '' COMMENT '用户名称',
        `nick_name`   varchar(32) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '用户昵称',
        `password`    varchar(32)                       NOT NULL DEFAULT '' COMMENT '密码',
        `phone`       varchar(16)                       NOT NULL DEFAULT '' COMMENT '手机号码',
        `email`       varchar(64)                                DEFAULT '' COMMENT '邮箱',
        `create_time` timestamp                         NULL     DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间',
        PRIMARY KEY (`id`),
        UNIQUE KEY `uq_nick_name` (`nick_name`),
        UNIQUE KEY `uq_user_name` (`user_name`)
    ) ENGINE = InnoDB
      DEFAULT CHARSET = utf8 COMMENT ='用户信息表';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    1.2 文件信息表 file_info

    字段解释
    id文件序号,自动递增,主键
    md5文件md5, 识别文件的唯一表示(身份证号)
    file_id文件id-/group1/M00/00/00/xxx.png
    url文件url 192.168.1.1:80/group1/M00/00/00/xxx.png - 下载的时候使用
    size文件大小, 以字节为单位
    type文件类型: png, zip, mp4……
    count文件引用计数, 默认为1 每增加一个用户拥有此文件,此计数器+1
    CREATE TABLE `file_info`
    (
        `id`      bigint(20)   NOT NULL AUTO_INCREMENT COMMENT '文件序号,自动递增,主键',
        `md5`     varchar(256) NOT NULL COMMENT '文件md5',
        `file_id` varchar(256) NOT NULL COMMENT '文件id:/group1/M00/00/00/xxx.png',
        `url`     varchar(512) NOT NULL COMMENT '文件url 192.168.52.139:80/group1/M00/00/00/xxx.png',
        `size`    bigint(20)  DEFAULT '0' COMMENT '文件大小, 以字节为单位',
        `type`    varchar(32) DEFAULT '' COMMENT '文件类型: png, zip, mp4……',
        `count`   int(11)     DEFAULT '0' COMMENT '文件引用计数,默认为1。每增加一个用户拥有此文件,此计数器+1',
        PRIMARY KEY (`id`)
    ) ENGINE = InnoDB
      DEFAULT CHARSET = utf8 COMMENT ='文件信息表';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    1.3 用户文件列表表 user_file_list

    字段解释
    id序号,自动递增,主键
    user文件所属用户
    md5文件md5
    create_time文件创建时间
    file_name文件名字
    shared_status共享状态, 0为没有共享, 1为共享
    pv文件下载量,默认值为0,下载一次加1
    CREATE TABLE `user_file_list`
    (
        `id`            int(11)      NOT NULL AUTO_INCREMENT COMMENT '编号',
        `user`          varchar(32)  NOT NULL COMMENT '文件所属用户',
        `md5`           varchar(256) NOT NULL COMMENT '文件md5',
        `create_time`   timestamp    NULL DEFAULT CURRENT_TIMESTAMP COMMENT '文件创建时间',
        `file_name`     varchar(128)      DEFAULT NULL COMMENT '文件名字',
        `shared_status` int(11)           DEFAULT NULL COMMENT '共享状态, 0为没有共享, 1为共享',
        `pv`            int(11)           DEFAULT NULL COMMENT '文件下载量,默认值为0,下载一次加1',
        PRIMARY KEY (`id`)
    ) ENGINE = InnoDB
      DEFAULT CHARSET = utf8 COMMENT ='用户文件列表';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    1.4 用户文件数量表 user_file_count

    字段解释
    id序号,自动递增,主键
    user文件所属用户
    count拥有文件的数量
    CREATE TABLE `user_file_count`
    (
        `id`    int(11)      NOT NULL AUTO_INCREMENT,
        `user`  varchar(128) NOT NULL COMMENT '文件所属用户',
        `count` int(11) DEFAULT NULL COMMENT '拥有文件的数量',
        PRIMARY KEY (`id`),
        UNIQUE KEY `user_UNIQUE` (`user`)
    ) ENGINE = InnoDB
      DEFAULT CHARSET = utf8 COMMENT ='用户文件数量表';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1.5 共享文件列表 share_file_list

    字段解释
    id序号,自动递增,主键
    user文件所属用户
    md5文件md5
    file_name文件名字
    pv文件下载量,默认值为1,下载一次加1
    create_time文件共享时间
    CREATE TABLE `share_file_list`
    (
        `id`          int(11)      NOT NULL AUTO_INCREMENT COMMENT '编号',
        `user`        varchar(32)  NOT NULL COMMENT '文件所属用户',
        `md5`         varchar(256) NOT NULL COMMENT '文件md5',
        `file_name`   varchar(128)      DEFAULT NULL COMMENT '文件名字',
        `pv`          int(11)           DEFAULT '1' COMMENT '文件下载量,默认值为1,下载一次加1',
        `create_time` timestamp    NULL DEFAULT CURRENT_TIMESTAMP COMMENT '文件共享时间',
        PRIMARY KEY (`id`)
    ) ENGINE = InnoDB
      DEFAULT CHARSET = utf8 COMMENT ='共享文件列表';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    1.6 共享图片列表 share_picture_list

    字段解释
    id序号,自动递增,主键
    user图片所属用户
    filemd5图片md5
    file_name图片名字
    urlmd5图片urlmd5
    pv图片下载量,默认值为1,下载一次加1
    create_time图片共享时间
    CREATE TABLE `share_picture_list`
    (
        `id`          int(11)      NOT NULL AUTO_INCREMENT COMMENT '编号',
        `user`        varchar(32)  NOT NULL COMMENT '文件所属用户',
        `filemd5`     varchar(256) NOT NULL COMMENT '文件md5',
        `file_name`   varchar(128)      DEFAULT NULL COMMENT '文件名字',
        `urlmd5`      varchar(256) NOT NULL COMMENT '图床urlmd5',
        `pv`          int(11)           DEFAULT '1' COMMENT '文件下载量,默认值为1,下载一次加1',
        `create_time` timestamp    NULL DEFAULT CURRENT_TIMESTAMP COMMENT '文件创建时间',
        PRIMARY KEY (`id`)
    ) ENGINE = InnoDB
      DEFAULT CHARSET = utf8 COMMENT ='共享图片列表';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    1.7 导入数据库

    gopher.sql在前言源码中

    root@wxf:/temp# mysql -uroot -p123456
    mysql> source /temp/gopher.sql
    
    • 1
    • 2

    2. 后端接口设计

    2.1 注册 - reg

    注册是一个简单的 HTTP 接口,根据用户输入的注册信息,创建一个新的用户。

    • 请求 URL
    URLhttp://ip:port/api/reg
    请求方式POST
    HTTP版本 1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义规则说明是否必须缺省值
    userName用户名称不能超过 32 个字符必填
    nickName用户昵称不能超过 32 个字符必填
    firstPwd密码md5加密后的值必填
    phone手机号码不能超过 16 个字符可选
    email邮箱必须符合 email 规范可选
    • 返回结果参数说明
    名称含义规则说明
    code结果值0:成功 1:失败 2:用户存在
    1. 客户端
    # URL
    http://192.168.1.1/api/reg
    # post数据格式
    {
    	userName:xxxx,
        nickName:xxx,
        firstPwd:xxx,
        phone:xxx,
        email:xxx
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. 服务器端-Nginx
    location /api/reg
    {
        # 转发数据
        fastcgi_pass localhost:10000;
        include fastcgi.conf;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 编写fastcgi程序
    int main()
    {
        while(FCGI_Accept() >= 0)
        {
            // 1. 根据content-length得到post数据块的长度
            // 2. 根据长度将post数据块读到内存
            // 3. 解析json对象, 得到用户名, 密码, 昵称, 邮箱, 手机号
            // 4. 连接数据库 - mysql, oracle
            // 5. 查询, 看有没有用户名, 昵称冲突 -> {"code":"2"}
            // 6. 有冲突 - 注册失败, 通知客户端
            // 7. 没有冲突 - 用户数据插入到数据库中
            // 8. 成功-> 通知客户端 -> {"code":"0"}
            // 9. 通知客户端回传的字符串的格式
            printf("content-type: application/json\r\n");
            printf("{\"code\":\"0\"}");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.2 登陆 - login

    登录,根据用户输入的登录信息,登录进入到后台系统。

    • 请求 URL
    URLhttp://ip:port/api/login
    请求方式POST
    HTTP版本 1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义规则说明是否必须缺省值
    user用户名称不能超过 32 个字符必填
    pwd密码md5 加密后的值必填
    • 返回结果参数说明
    名称含义规则说明
    code结果值0: 成功 1: 失败
    token令牌每次登录后,生成的 token 不一样,后续其他接口请求时,需要带上 token。
    1. 客户端
    #URL
    http://192.168.1.1:80/api/login
    # post数据格式
    {
        user:xxxx,
        pwd:xxx
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 服务器端
    location /aip/login
    {
        # 转发数据
        fastcgi_pass localhost:10001;
        include fastcgi.conf;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 编写fastcgi程序
    int main()
    {
        while(FCGI_Accept() >= 0)
        {
            // 1. 根据content-length得到post数据块的长度
            // 2. 根据长度将post数据块读到内存
            // 3. 解析json对象, 得到用户名, 密码
            // 4. 连接数据库 - mysql, oracle
            // 5. 查询, 根据用户名密码查询有没有这条记录
            // 6. 有记录- 登陆成功-生成token-> {"code":"0","token":"xxxx"}
            // 7. 没有记录- 登陆失败-> {"code":"1","token":"faild"}
            printf("content-type: application/json\r\n");
            printf("{\"code\":\"0\",\"token\":\"xxx\"}");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    token -> 客户端成功连接了服务器, 服务器针对于客户端的个人信息生成了一个唯一的身份标识
    	- 可以按照每个人的身份证号理解
        - 服务器将这个token发送给客户端
    	- 客户端token的使用:
    		- 使用: 登录成功之后, 向服务器在发送任意请求都需要携带该token值
    	- 服务器端的使用和保存:
    		- 使用: 接收客户端发送的token, 和服务器端保存的token进行认证
    			- 认证成功: 合法客户端, 失败: 客户端非法
    		- 保存: 服务器需要保存所有客户端的token
    				- 数据库中
    				- 配置文件 -> 效率低
    				- redis中 -> 效率最高
    
    token = (客户端信息+随机数)*des*md5*base64
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.3 上传文件 - 秒传 - md5

    上传文件的时候:

    • 先调用 md5 接口判断服务器是否有该文件,如果 md 调用成功,则说明服务器已经存在该文件,客户端不需要再去调用 upload 接口上传文件。
    • 如果不成功则客户端继续调用 upload 接口上传文件。
    • 尝试秒传 -> 文件并没上传
      • 给服务器发送的不是文件内容, 是文件的哈希值
      • 在服务器端收到哈希值, 查询数据库
        • 查到了 -> 秒传成功
        • 没查到 -> 秒传失败, 需要进行一个真正的上传操作
    • 进行真正的上传
      • 需要的时间长
      • 上传有文件内容, 文件的哈希值
        • 文件内容 -> 分布式文件系统
        • 哈希值 -> 数据库
    • 请求 URL
    URLhttp://ip:port/api/md5
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义规则说明是否必须缺省值
    token令牌同上必填
    md5md5 值不能超过 32 个字符必填
    filename文件名称不能超过 128 个字符必填
    user用户名称不能超过 32 个字符必填
    • 返回结果参数说明
    名称含义规则说明
    code结果值0: 秒传成功1: 秒传失败 2: 已有该文件 3: token 校验失败
    1. 客户端
    # url
    http://127.0.0.1:80/api/md5
    # post数据格式
    {
        user:xxxx,
        token:xxxx,
        md5:xxx,
        fileName: xxx
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 服务器
    location /api/md5
    {
        # 转发数据
        fastcgi_pass localhost:10003;
        include fastcgi.conf;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • fastCGI程序编写
    int main()
    {
        while(FCGI_Accept() >= 0)
        {
            // 1. 得到post数据的长度
            char* length = getenv("content-length");
            int len = atoi(length);
            // 2. 根据len将数据读到内存中, json对象字符串
            // 3. 解析json对象, user,md5, token, fileName
            // 4. token认证 , 查询redis/数据库
            //     -- 成功: 继续后续操作, 失败, 返回, 给客户端一个结果
            // 5. 打开数据库, 并查询md5是否存在
            //     -- 存在   {"code":"0"}
            			-- 上传成功之后,业务逻辑--->存数据库一些相关信息
            //     -- 不存在  {"code":"1"}
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.4 上传文件 - 真上传 - upload

    上传文件

    • 请求 URL
    URLhttp://ip:port/api/upload
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/octet-stream
    • 请求参数
    参数名含义规则说明是否必须缺省值
    token密码md5加密后的值必填
    • 返回结果参数说明
    名称含义规则说明
    code结果值0: 上传成功 1: 上传失败
    • 客户端
    # url
    http://127.0.0.1:80/api/upload
    # post数据格式
    ------WebKitFormBoundary88asdgewtgewx\r\n
    # 文件信息
    Content-Disposition: form-data; user="wxf"; filename="xxx.jpg"; md5="xxxx"; size=10240
    Content-Type: image/jpg
    # 真正的文件内容xxxxxxxxxxxxxxx
    ------WebKitFormBoundary88asdgewtgewx--
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 服务器
    location /api/upload
    {
        # 转发数据
        fastcgi_pass localhost:10002;
        include fastcgi.conf;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 服务器端fastCGI 部分 伪代码
    // fastcgi程序
    int main()
    {
        while(FCGI_Accept() >= 0)
        {
            // 1. 读一次数据 - buf, 保证能够将分界线和两个头都装进去
            char buf[4096];
            // len == 实际读出的字节数
            int len = fread(buf, 1, 4096, stdin);
            // 2. 跳过第一行的分界线
            len = len - 第一行的长度
            // 3. 将第二行中的user, filename, md5, size的值读出 -> 内存
            len = len - 第二行的长度;
            // 4. 跳过第3行
            len = len-第三行的长度
            // 5. 跳过空行
            len = len-空行的长度;
            // 6. 现在得到的位置的就是传输的真正数据的正文开始
            // 7. 循环的将剩余的内容读出, 有必要就写磁盘
            // 8. 读完了, 将最后的分界线剔除
            // 9. 以上8步处理完毕, 文件内容就被扣出来了
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    #include 
    #include 
    #include 
    #include 
    #include 
    #include "fcgi_stdio.h"
    
    int recv_save_file(char *user, char *filename, char *md5, long *p_size) {
        int ret = 0;
        char *file_buf = NULL;
        char *begin = NULL;
        char *p, *q, *k;
    
        char content_text[512] = {0}; //文件头部信息
        char boundary[512] = {0};     //分界线信息
    
        //==========> 开辟存放文件的 内存 <===========
        file_buf = (char *) malloc(4096);
        if (file_buf == NULL) {
            return -1;
        }
    
        //从标准输入(web服务器)读取内容
        int len = fread(file_buf, 1, 4096, stdin);
        if (len == 0) {
            ret = -1;
            free(file_buf);
            return ret;
        }
    
        //===========> 开始处理前端发送过来的post数据格式 <============
        begin = file_buf;    //内存起点
        p = begin;
    
        /*
           ------WebKitFormBoundary88asdgewtgewx\r\n
           Content-Disposition: form-data; user="mike"; filename="xxx.jpg"; md5="xxxx"; size=10240\r\n
           Content-Type: application/octet-stream\r\n
           \r\n
           真正的文件内容\r\n
           ------WebKitFormBoundary88asdgewtgewx
           */
    
        //get boundary 得到分界线, ------WebKitFormBoundary88asdgewtgewx
        p = strstr(begin, "\r\n");
        if (p == NULL) {
            ret = -1;
            free(file_buf);
            return ret;
        }
    
        //拷贝分界线
        strncpy(boundary, begin, p - begin);
        boundary[p - begin] = '\0';   //字符串结束符
        //LOG(UPLOAD_LOG_MODULE, UPLOAD_LOG_PROC,"boundary: [%s]\n", boundary);
    
        p += 2; //\r\n
        //已经处理了p-begin的长度
        len -= (p - begin);
        //get content text head
        begin = p;
        //Content-Disposition: form-data; user="mike"; filename="xxx.jpg"; md5="xxxx"; size=10240\r\n
        p = strstr(begin, "\r\n");
        if (p == NULL) {
            ret = -1;
            free(file_buf);
            return ret;
        }
        strncpy(content_text, begin, p - begin);
        content_text[p - begin] = '\0';
    
        p += 2;//\r\n
        len -= (p - begin);
    
        //========================================获取文件上传者
        //Content-Disposition: form-data; user="mike"; filename="xxx.jpg"; md5="xxxx"; size=10240\r\n
        q = begin;
        q = strstr(begin, "user=");
        q += strlen("user=");
        q++;    //跳过第一个"
        k = strchr(q, '"');
        strncpy(user, q, k - q);  //拷贝用户名
        user[k - q] = '\0';
    
        //========================================获取文件名字
        //"; filename="xxx.jpg"; md5="xxxx"; size=10240\r\n
        begin = k;
        q = begin;
        q = strstr(begin, "filename=");
        q += strlen("filename=");
        q++;    //跳过第一个"
        k = strchr(q, '"');
        strncpy(filename, q, k - q);  //拷贝文件名
        filename[k - q] = '\0';
    
        //========================================获取文件MD5码
        //"; md5="xxxx"; size=10240\r\n
        begin = k;
        q = begin;
        q = strstr(begin, "md5=");
        q += strlen("md5=");
        q++;    //跳过第一个"
        k = strchr(q, '"');
        strncpy(md5, q, k - q);   //拷贝文件名
        md5[k - q] = '\0';
    
        //========================================获取文件大小
        //"; size=10240\r\n
        begin = k;
        q = begin;
        q = strstr(begin, "size=");
        q += strlen("size=");
        k = strstr(q, "\r\n");
        char tmp[256] = {0};
        strncpy(tmp, q, k - q);   //内容
        tmp[k - q] = '\0';
        *p_size = strtol(tmp, NULL, 10); //字符串转long
    
        begin = p;
        p = strstr(begin, "\r\n");
        // 跳过最后一个请求头行和空行
        p += 4; //\r\n\r\n
        // len就是正文的起始位置到数组结束的长度
        len -= (p - begin);
    
        //下面才是文件的真正内容
        /*
           ------WebKitFormBoundary88asdgewtgewx\r\n
           Content-Disposition: form-data; user="mike"; filename="xxx.jpg"; md5="xxxx"; size=10240\r\n
           Content-Type: application/octet-stream\r\n
           \r\n
           真正的文件内容\r\n
           ------WebKitFormBoundary88asdgewtgewx
        */
        begin = p;
        // 将数组中剩余的数据(文件的内容), 写入到磁盘中
        int fd = open(filename, O_CREAT | O_WRONLY, 0664);
        write(fd, begin, len);
        // 1. 文件已经读完了
        // 2. 文件还没读完
        if (*p_size > len) {
            // 读文件 -> 接收post数据
            // fread , read  , 返回值>0== 实际读出的字节数; ==0, 读完了; -1, error
            while ((len = fread(file_buf, 1, 4096, stdin)) > 0) {
                // 读出的数据写文件
                write(fd, file_buf, len);
            }
        }
        // 3. 解写入到文件中的分界线删除
        ftruncate(fd, *p_size);
        close(fd);
    
        free(file_buf);
        return ret;
    }
    
    int main() {
        while (FCGI_Accept() >= 0) {
            // int recv_save_file(char *user, char *filename, char *md5, long *p_size)
            char user[24];
            char fileName[32];
            char md5[64];
            long size;
            recv_save_file(user, fileName, md5, &size);
            // filename对应的文件上传到fastdfs
            // 上传得到的文件ID需要写数据库
            // 给客户端发送响应数据
            printf("Content-type: text/plain\r\n\r\n");
            printf("用户名: %s\n", user);
            printf("文件名: %s, md5: %s, size: %ld\n", fileName, md5, size);
            printf("客户端处理数据完毕, 恭喜...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173

    2.5 获取用户文件数量 - myfiles

    获取用户文件数量

    • 请求 URL
    URLhttp://ip:port/api/myfiles?cmd=count
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义规则说明是否必须缺省值
    tokentoken同上必填
    user用户名称不能超过 32 个字符必填
    • 返回结果参数说明
    名称含义规则说明
    code结果值0:验证成功 1:验证失败
    total文件数量
    1. 客户端
    url : http://127.0.0.1:80/api/myfiles?cmd=count
    post数据 :{   "user": "wxf",   "token": "xxxx"   }
    
    • 1
    • 2
    1. 服务器
    服务器添加的nginx指令:
    location /api/myfiles
    {
        fastcgi_pass localhost:10004;
        include fastcgi.conf;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 编写fastcgi程序
    // fastcgi程序
    int main()
    {
    	while(FCGI_Accept() >= 0)
        {
            // 接收数据
            // 将url?后边的内容取出
            // cmd=normal; cmd=count
            char* type = getenv("QUERY_STRING");
            // 将 = 后的内容取出, 保存在数组cmd中
            if(strcmp(cmd, "count") == 0)
            {
                // 解析数据, user, token
                // token认证
                // 认证成功, 查询数据库   
            }
    		else if()
            {
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    {
    	"total":"8",
    	"code":"0"     // token验证成功
    }
    
    • 1
    • 2
    • 3
    • 4

    2.6 获取用户文件信息 - myfiles

    获取用户文件信息

    • 请求 URL
    URLhttp://ip:port/api/myfiles?cmd=见下文
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    cmd = normal 或 pvasc 或 pvdesc
    
    • 1
    • 请求参数
    参数名含义规则说明是否必须缺省值
    token令牌同上必填
    user用户名称不能超过 32 个字符必填
    count文件个数文件个数需大于 0必填
    start开始位置必填
    • 返回结果参数说明
    名称含义规则说明
    files文件结果集见下
    "code": 0 正常,1 失败
    "count": 返回的当前文件数量,比如 2
    "total": 个人文件总共的数量
    "user": 用户名称,
    "md5": md5 值,
    "create_time": 创建时间,
    "file_name": 文件名,
    "share_status": 共享状态, 0 为没有共享, 1 为共享
    "pv": 文件下载量,下载一次加 1
    "url": URL,
    "size": 文件大小,
    "type": 文件类型
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    1. 客户端

      获取用户文件信息http://127.0.0.1:80/myfiles&cmd=normal
      按下载量升序http://127.0.0.1:80/myfiles?cmd=pvasc
      按下载量降序http://127.0.0.1:80/myfiles?cmd=pvdesc
      post数据{ “user”: “wxf” , “token”: “xxxx”, “start”: 0, “count”: 10 }
    http://127.0.0.1:80/api/myfiles&cmd=normal
    # post body数据
    {
        "count": 2, 
        "start": 0, 
        "token": "3a58ca22317e637797f8bcad5c047446", 
        "user": "wxf"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    # 服务器返回的json
    {
        "code": 0, 
        "count": 2, # 如果为 0 则不需要解析 files
        "total": 2, # 个人文件总共的数量
        "files": [
            {
                "user": "wxf", 
                "md5": "6c5fa2864bb264c91167258b3e478fa0", 
                "create_time": "2022-09-09 23:32:01", 
                "file_name": "Qt5Svg.dll", 
                "share_status": 0, 
                "pv": 1, 
                "url": "http://192.168.109.101:80/group1/M00/00/00/eBuDxWCfQHSATopyAAV8AJV_1mw866.dll", 
                "size": 359424, 
                "type": "dll"
            }, 
            {
                "user": "wxf", 
                "md5": "c32b5d82be3d2fcec96de06e81f87814", 
                "create_time": "2022-09-09 23:32:01", 
                "file_name": "1.png", 
                "share_status": 0, 
                "pv": 0, 
                "url": "http://192.168.109.101:80/group1/M00/00/00/eBuDxWCfQPCAapRFAACtu7eiL0000.png", 
                "size": 44475, 
                "type": "png"
            }
        ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    # 文件数量为 0 的场景
    {
        "code": 0, 
        "count": 0
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.7 获取共享列表数量 - sharefiles

    获取共享列表数量

    • 请求 URL
    URLhttp://ip:port/api/sharefiles?cmd=count
    请求方式GET
    HTTP 版本1.1
    Content-Typeapplication/x-www-form-urlencoded

    • 请求参数: 无

      

    • 返回结果参数说明
    名称含义规则说明
    code结果码0:正常;1:失败
    total总数量
    1. 客户端
    get请求对应的url
    http://127.0.0.1:80/sharefiles&cmd=count
    
    • 1
    • 2
    1. 服务器
    location /api/sharefiles
    {
        # 转发数据
        fastcgi_pass localhost:10005;
        include fastcgi.conf;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.8 获取共享列表文件 - sharefiles

    获取共享列表文件

    • 请求 URL
    URLhttp://ip:port/api/sharefiles?cmd=normal
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义是否必须缺省值
    count数量必填
    start开始位置必填
    • 返回结果参数说明
    名称含义规则说明
    files文件结果集见下
    "code":0:正常;1:失败
    "count": 2, // 分页返回数量,如果为 0 则不需要解析 files
    "total": 2, 总的文件数量
    "user": 用户名称,
    "md5": md5 值,
    "create_time": 创建时间,
    "file_name": 文件名,
    "share_status": 共享状态, 0 为没有共享, 1 为共享
    "pv": 文件下载量,下载一次加 1
    "url": URL,
    "size": 文件大小,
    "type": 文件类型
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    1. 客户端
    请求的url, 获取共享文件信息
    http://127.0.0.1:80/api/sharefiles&cmd=normal
    
    • 1
    • 2
    /* post数据 */
    {
       "start": 0,
       "count": 1
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    # 返回结果
    {
        "code": 0, 
        "count": 1, 
        "total": 2, 
        "files": [
            {
                "user": "wxf", 
                "md5": "602fdf30db2aacf517badf4565124f51", 
                "file_name": "Makefile", 
                "share_status": 1, 
                "pv": 0, 
                "create_time": "2022-09-09 23:49:15", 
                "url": "http://192.168.109.101:80/group1/M00/00/00/rBAAD17_Jn6AMiuAACBBC5AIsc2532509", 
                "size": 33028, 
                "type": "null"
            }
        ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2.9 下载榜 - sharefiles

    • 请求 URL
    URLhttp://ip:port/api/sharefiles?cmd=pvdesc
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义是否必须缺省值
    count数量必填
    start开始位置必填
    • 返回结果参数说明
    名称含义规则说明
    files文件结果集“filename”: 文件名,“pv”: 文件下载量,下载一次加 1
    code返回码0:正常;1:失败
    cout分页文件数量比如 1,如果为 0 则不需要解析 files
    total总文件数量比如 2

    2.10 文件分享 - dealfile

    分享文件

    • 请求 URL
    URLhttp://ip:port/api/dealfile?cmd=share
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义规则说明是否必须缺省值
    token令牌同上必填
    user用户名称不能超过 32 个字符必填
    md5md5 值md5 加密后的值必填
    filename文件名称不能超过 128 个字符必填
    • 返回结果参数说明
    名称含义规则说明
    code结果值见下
    0: 成功
    1: 失败
    3: 别人已经分享此文件
    4: token 验证失败
    
    • 1
    • 2
    • 3
    • 4
    1. 客户端
    请求的url
    http://127.0.0.1:80/api/dealfile?cmd=share
    
    • 1
    • 2
    /* post数据格式 */
    {
       "user": "wxf",
       "token": "xxxx",
       "md5": "xxx",
       "filename": "xxx"
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    /* 返回结果 */
    {
    	"code": 0
    }
    
    • 1
    • 2
    • 3
    • 4
    • 服务端
    location /api/dealfile
    {
        # 转发数据
        fastcgi_pass localhost:10006;
        include fastcgi.conf;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.11 文件删除 - dealfile

    文件删除

    • 请求 URL
    URLhttp://ip:port/api/dealfile?cmd=del
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义规则说明是否必须缺省值
    token令牌同上必填
    user用户名称不能超过 32 个字符必填
    md5md5 值md5 加密后的值必填
    filename文件名称不能超过 128 个字符必填
    • 返回结果参数说明
    名称含义规则说明
    code结果值0: 成功;1: 失败
    1. 客户端
    请求的url
    http://127.0.0.1:80/api/dealfile?cmd=del
    
    • 1
    • 2
    /* post数据格式 */
    {
        "user": "wxf",
        "token": "xxxx",
        "md5": "xxx",
        "filename": "xxx"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    /* 返回结果 */
    {
    	"code": 0
    }
    
    • 1
    • 2
    • 3
    • 4

    2.12 文件下载之后, 下载量pv字段的处理 - dealfile

    是用来更新指定文件的下载量,每次成功下载一个文件成功后,调用该接口更新对应文件的 pv 值。

    • 请求 URL
    URLhttp://ip:port/api/dealfile?cmd=pv
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义规则说明是否必须缺省值
    token令牌同上必填
    user用户名称不能超过 32 个字符必填
    md5md5 值md5 加密后的值必填
    filename文件名称不能超过 128 个字符必填
    • 返回结果参数说明
    名称含义规则说明
    code结果值0: 成功;1: 失败
    1. 客户端
    请求的url: http://127.0.0.1:80/api/dealfile?cmd=pv
    通过值请求更新数据库中该文件对应的下载量字段值
    
    • 1
    • 2
    /* post数据块 */
    {
       "user": "wxf",
       "token": "xxx",
       "md5": "xxx",
       "filename": "xxx"
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    /* 返回结果 */
    {
    	"code": 0
    }
    
    • 1
    • 2
    • 3
    • 4

    2.13 取消分享文件 - dealsharefile

    • 请求 URL
    URLhttp://ip:port/api/dealsharefile?cmd=cancel
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义规则说明是否必须缺省值
    user用户名称不能超过 32 个字符必填
    md5md5 值md5 加密后的值必填
    filename文件名称不能超过 128 个字符必填
    • 返回结果参数说明
    名称含义规则说明
    code结果值0: 成功;1: 失败
    1. 客户端
    http://127.0.0.1/api/dealsharefile?cmd=cancel
    
    • 1
    /* post数据块格式 */
    {
    	"user": "wxf",
    	"md5": "xxx",
    	"filename": "xxx"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    /* 返回结果 */
    {
    	"code": 0
    }
    
    • 1
    • 2
    • 3
    • 4
    • 服务端
    location /api/dealsharefile
    {
        # 转发数据
        fastcgi_pass localhost:10007;
        include fastcgi.conf;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.14 转存文件 - dealsharefile

    • 请求 URL
    URLhttp://ip:port/api/dealsharefile?cmd=save
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义规则说明是否必须缺省值
    user用户名称不能超过 32 个字符必填
    md5md5 值md5 加密后的值必填
    filename文件名称不能超过 128 个字符必填
    • 返回结果参数说明
    名称含义规则说明
    code结果值0: 成功;1: 失败 ; 5: 文件已存在
    1. 客户端
    # 调用接口
    http://127.0.0.1/api/dealsharefile?cmd=save
    
    • 1
    • 2
    /* post数据块格式 */
    {
    	"user": "wxf",
    	"md5": "xxx",
    	"filename": "xxx"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    /* 返回结果 */
    {
    	"code": 0
    }
    
    • 1
    • 2
    • 3
    • 4

    2.15 共享文件下载pv标志处理 - dealsharefile

    即是共享文件下载成功后,发该 url 的请求,该文件下次数量+1

    • 请求 URL
    URLhttp://ip:port/api/dealsharefile?cmd=pv
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义规则说明是否必须缺省值
    user用户名称不能超过 32 个字符必填
    md5md5 值md5 加密后的值必填
    filename文件名称不能超过 128 个字符必填
    • 返回结果参数说明
    名称含义规则说明
    code结果值0: 成功;1: 失败

    2.16 图片分享 - sharepic

    • 请求 URL
    URLhttp://ip:port/api/sharepic?cmd=share
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义规则说明是否必须缺省值
    token令牌同上必填
    user用户名称不能超过 32 个字符必填
    md5md5 值md5 加密后的值必填
    filename文件名称不能超过 128 个字符必填
    • 返回结果参数说明
    名称含义规则说明
    code结果值0: 成功;1: 失败;4: token 验证失败
    urlmd5分享图片的标识取消分享时也要该标识

    2.17 请求浏览图片 - sharepic

    请求接口 http://ip:port/api/sharepic?cmd=browse,主要用来返回具体的图片下载地址,对图片浏览量pv+1

    • 请求 URL
    URLhttp://ip:port/api/sharepic?cmd=browse
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义是否必须缺省值
    urlmd5分享图片的标识必填
    • 返回结果参数说明
    名称含义规则说明
    code结果值0:请求到 url 下载的 url;1:提取码错误;2:文件已经被删除;
    url图片下载地址
    user分享者分享者
    time分享时间
    pv浏览次数pv=pv+1

    2.18 我的图片分享 - sharepic

    和我的文件类似显示自己的分享图片信息

    • 请求 URL
    URLhttp://ip:port/api/sharepic?cmd=normal
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义规则说明是否必须缺省值
    token令牌同上必填
    user用户名称不能超过 32 个字符必填
    count数量必填
    start开始位置必填
    名称含义规则说明
    files文件结果集见下
    "code":0:正常;1:失败
    "count": 2, # 分页返回数量,如果为 0 则不需要解析 files
    "total": 2, 总的文件数量
    "user": 用户名称,
    "filemd5": 文件 md5 值,
    "urlmd5": 图传共享时的 URL,
    "create_time": 创建时间,
    "file_name": 文件名,
    "pv": 文件浏览量,浏览一次加 1
    "size": 文件大小
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.19 取消图片分享 - sharepic

    • 请求 URL
    URLhttp://ip:port/api/sharepic?cmd=cancel
    请求方式POST
    HTTP 版本1.1
    Content-Typeapplication/json
    • 请求参数
    参数名含义规则说明是否必须缺省值
    token令牌同上必填
    user用户名称不能超过 32 个字符必填
    md5md5 值md5 加密后的值必填
    • 返回结果参数说明
    名称含义规则说明
    code结果值0: 成功;1: 失败;4: token 验证失败

    3. 总结

    上文的服务器配置的location的端口有些是写错了,只是个示例,在nginx.conf配置的端口要与spawn-fcgi相对应,别搞混了。

    location /api/login {
    	fastcgi_pass 127.0.0.1:10000;
        include fastcgi.conf;
    }
    
    location /api/reg {
        fastcgi_pass 127.0.0.1:10001;
        include fastcgi.conf;
    }
    
    location /api/upload {
        fastcgi_pass 127.0.0.1:10002;
        include fastcgi.conf;
    }
    
    location /api/md5 {
        fastcgi_pass 127.0.0.1:10003;
        include fastcgi.conf;
    }
    
    location /api/myfiles {
        fastcgi_pass 127.0.0.1:10004;
        include fastcgi.conf;
    }
    
    location /api/dealfile {
        fastcgi_pass 127.0.0.1:10005;
        include fastcgi.conf;
    }
    
    location /api/sharefiles {
        fastcgi_pass 127.0.0.1:10006;
        include fastcgi.conf;
    }
    location /api/dealsharefile {
        fastcgi_pass 127.0.0.1:10007;
        include fastcgi.conf;
    }
    
    location /api/sharepic {
        fastcgi_pass 127.0.0.1:10008;
        include fastcgi.conf;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    # ******************************* 重新启动CGI进程 ******************************* 
    if [ "$START" -eq 1 ];then
        # 登录
        echo -n "登录:"
        spawn-fcgi -a 127.0.0.1 -p 10000 -f ./bin_cgi/login
        # 注册
        echo -n "注册:"
        spawn-fcgi -a 127.0.0.1 -p 10001 -f ./bin_cgi/register
        # 上传文件
        echo -n "上传:"
        spawn-fcgi -a 127.0.0.1 -p 10002 -f ./bin_cgi/upload
        # MD5秒传
        echo -n "MD5:"
        spawn-fcgi -a 127.0.0.1 -p 10003 -f ./bin_cgi/md5
        # 我的文件
        echo -n "MyFile:"
        spawn-fcgi -a 127.0.0.1 -p 10004 -f ./bin_cgi/myfiles
        # 分享删除文件
        echo -n "DealFile:"
        spawn-fcgi -a 127.0.0.1 -p 10005 -f ./bin_cgi/dealfile
        # 共享文件列表
        echo -n "ShareList:"
        spawn-fcgi -a 127.0.0.1 -p 10006 -f ./bin_cgi/sharefiles
        # 共享文件pv字段处理、取消分享、转存文件
        echo -n "DealShare:"
        spawn-fcgi -a 127.0.0.1 -p 10007 -f ./bin_cgi/dealsharefile
    	  # 图床共享图片
        echo -n "SharePicture:"
        spawn-fcgi -a 127.0.0.1 -p 10008 -f ./bin_cgi/sharepicture
        echo "CGI 程序已经成功启动 ^_^..."
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  • 相关阅读:
    当下企业源代码数据防泄密工作该如何进行
    vue3项目中引用tailwindcss与heroicons
    1027. 最长等差数列(leetcode)
    【Python】牛客HJ43迷宫问题
    【UE数字孪生学习笔记】 Gameplay框架之TArray
    318. 最大单词长度乘积
    手把手教会你怎么压缩JPG图片
    更改 HIVE 表字段数据类型有哪些注意事项?
    在系统识别 App 中估计传递函数模型
    19 04-读取DTC快照信息
  • 原文地址:https://blog.csdn.net/qq_42956653/article/details/126783433