[云盘](二)我的文件和共享列表后台实现

后台代码实现

  • 我的文件列表
    • Mian
    • 读取配置信息
    • 解析json登录token(cmd为count)
    • 解析jason(cmd不为count)
    • 获取用户文件个数
    • 获取用户文件列表
    • 源码
  • 共享文件列表
    • main
    • 获取共享文件个数
    • 前端分页请求包
    • 获得普通共享文件列表
    • 共享文件排行榜
    • 源码

我的文件列表

  • 业务逻辑是,点击我的文件,会在展示界面展示出该用户所有文件
  • 单机图标会显示选项下载,分享,删除,属性
  • 单机空白处会显示选型,会显示选项:按下载量排序/按下载量排序/刷新/上传
  • 其中上传操作也可以点击界面中的上传图标,然后会弹出窗口选择要上传的文件,上传过程是一个toolbar会显示进度在传输列表中

在这里插入图片描述

  • 实质是两张表联查 file_info, user_file_list ,做了物理分页,根据指令按照pv字段做升序降序排列

Mian

  • 读取配置文件 read_cfg();拿到数据库连接

  • while (FCGI_Accept() >= 0)等待连接

  • 业务主要分两种,一是只想知道用户有多少个文件,另一个是普通排序,按照pv升降序排序;均为post请求;为post请求时,由环境变量cmd拿到请求指令,由buf缓冲区拿到数据

  • cmd为count,获取用户文件个数if (strcmp(cmd, “count”) == 0) ,查表 get_user_files_count(user, ret); //获取用户文件个数

  • cmd为normal;pvacs;pvdesc;获取用户文件列表 get_user_filelist(cmd, user, start, count);

  • 需要注意的是,在fcgi程序中,直接fread是从标准输入读,就是从web服务器读;直接printf就是往标准输出,也是往web服务器(cgi程序利用I.O重定向技术)

      	int main()
      			{
      			    //count 获取用户文件个数
      			    //display 获取用户文件信息,展示到前端
      			    char cmd[20];
      			    char user[USER_NAME_LEN];
      			    char token[TOKEN_LEN];
      			
      		     //读取数据库配置信息
      		    read_cfg();
      		
      		    //阻塞等待用户连接
      		    while (FCGI_Accept() >= 0)
      		    {
      		
      		        // 获取URL地址 "?" 后面的内容
      		        char *query = getenv("QUERY_STRING");
      		
      		        //解析命令
      		        query_parse_key_value(query, "cmd", cmd, NULL);
      		        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cmd = %s\n", cmd);
      		
      		        char *contentLength = getenv("CONTENT_LENGTH");
      		        int len;
      		
      		        printf("Content-type: text/html\r\n\r\n");
      		
      		        if( contentLength == NULL )
      		        {
      		            len = 0;
      		        }
      		        else
      		        {
      		            len = atoi(contentLength); //字符串转整型
      		        }
      		
      		        if (len <= 0)
      		        {
      		            printf("No data from standard input.<p>\n");
      		            LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "len = 0, No data from standard input\n");
      		        }
      		        else
      		        {
      		            char buf[4*1024] = {0};
      		            int ret = 0;
      		            ret = fread(buf, 1, len, stdin); //从标准输入(web服务器)读取内容
      		            if(ret == 0)
      		            {
      		                LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "fread(buf, 1, len, stdin) err\n");
      		                continue;
      		            }
      		
      		            LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "buf = %s\n", buf);
      		
      		            if (strcmp(cmd, "count") == 0) //count 获取用户文件个数
      		            {
      		                get_count_json_info(buf, user, token); //通过json包获取用户名, token
      		
      		                //验证登陆token,成功返回0,失败-1
      		                ret = verify_token(user, token); //util_cgi.h
      		
      		                get_user_files_count(user, ret); //获取用户文件个数
      		
      		            }
      		            //获取用户文件信息 127.0.0.1:80/myfiles&cmd=normal
      		            //按下载量升序 127.0.0.1:80/myfiles?cmd=pvasc
      		            //按下载量降序127.0.0.1:80/myfiles?cmd=pvdesc
      		            else
      		            {
      		                int start; //文件起点
      		                int count; //文件个数
      		                get_fileslist_json_info(buf, user, token, &start, &count); //通过json包获取信息
      		                LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "user = %s, token = %s, start = %d, count = %d\n", user, token, start, count);
      		
      		                //验证登陆token,成功返回0,失败-1
      		                ret = verify_token(user, token); //util_cgi.h
      		                if(ret == 0)
      		                {
      		                     get_user_filelist(cmd, user, start, count); //获取用户文件列表
      		                }
      		                else
      		                {
      		                    char *out = return_status("111"); //token验证失败错误码
      		                    if(out != NULL)
      		                    {
      		                        printf(out); //给前端反馈错误码
      		                        free(out);
      		                    }
      		                }
      		
      		            }
      		
      		        }
      		
      		    }
      		
      		    return 0;
      		}
    

读取配置信息

  • 读取到MySQL配置文件信息

      void read_cfg()
      {
          //读取mysql数据库配置信息
          get_cfg_value(CFG_PATH, "mysql", "user", mysql_user);
          get_cfg_value(CFG_PATH, "mysql", "password", mysql_pwd);
          get_cfg_value(CFG_PATH, "mysql", "database", mysql_db);
          LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "mysql:[user=%s,pwd=%s,database=%s]", mysql_user, mysql_pwd, mysql_db);
      
          //读取redis配置信息
          //get_cfg_value(CFG_PATH, "redis", "ip", redis_ip);
          //get_cfg_value(CFG_PATH, "redis", "port", redis_port);
          //LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "redis:[ip=%s,port=%s]\n", redis_ip, redis_port);
      }
    

解析json登录token(cmd为count)

  • cmd为count时,此时的json包格式为

      {
      "token": "9e894efc0b2a898a82765d0a7f2c94cb",
       user:xxxx
      }
    
  • 此时,解析jason拿到token和username

      //解析的json包, 登陆token
      int get_count_json_info(char *buf, char *user, char *token)
      {
          int ret = 0;
      
      /*json数据如下
      {
          "token": "9e894efc0b2a898a82765d0a7f2c94cb",
          user:xxxx
      }
      */
    
      //解析json包
      //解析一个json字符串为cJSON对象
      cJSON * root = cJSON_Parse(buf);
      if(NULL == root)
      {
          LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_Parse err\n");
          ret = -1;
          goto END;
      }
    
      //返回指定字符串对应的json对象
      //用户
      cJSON *child1 = cJSON_GetObjectItem(root, "user");
      if(NULL == child1)
      {
          LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
          ret = -1;
          goto END;
      }
    
      //LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "child1->valuestring = %s\n", child1->valuestring);
      strcpy(user, child1->valuestring); //拷贝内容
    
      //登陆token
      cJSON *child2 = cJSON_GetObjectItem(root, "token");
      if(NULL == child2)
      {
          LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
          ret = -1;
          goto END;
      }
    
      //LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "child2->valuestring = %s\n", child2->valuestring);
      strcpy(token, child2->valuestring); //拷贝内容
    
      END:
          if(root != NULL)
          {
              cJSON_Delete(root);//删除json对象
              root = NULL;
          }
      
          return ret;
      }
    

解析jason(cmd不为count)

  • 作用是为了拿到user,token,start,count,用来给普通/升/降序同时物理分页查询准备

      	//解析的json包
      	int get_fileslist_json_info(char *buf, char *user, char *token, int *p_start, int *p_count)
      	{
      	    int ret = 0;
      	
      	    /*json数据如下
      	    {
      	        "user": "yoyo"
      	        "token": xxxx
      	        "start": 0
      	        "count": 10
      	    }
      	    */
      	
      	    //解析json包
      	    //解析一个json字符串为cJSON对象
      	    cJSON * root = cJSON_Parse(buf);
      	    if(NULL == root)
      	    {
      	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_Parse err\n");
      	        ret = -1;
      	        goto END;
      	    }
      	
      	    //返回指定字符串对应的json对象
      	    //用户
      	    cJSON *child1 = cJSON_GetObjectItem(root, "user");
      	    if(NULL == child1)
      	    {
      	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
      	        ret = -1;
      	        goto END;
      	    }
      	
      	    //LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "child1->valuestring = %s\n", child1->valuestring);
      	    strcpy(user, child1->valuestring); //拷贝内容
      	
      	    //token
      	    cJSON *child2 = cJSON_GetObjectItem(root, "token");
      	    if(NULL == child2)
      	    {
      	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
      	        ret = -1;
      	        goto END;
      	    }
      	
      	    strcpy(token, child2->valuestring); //拷贝内容
      	
      	    //文件起点
      	    cJSON *child3 = cJSON_GetObjectItem(root, "start");
      	    if(NULL == child3)
      	    {
      	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
      	        ret = -1;
      	        goto END;
      	    }
      	
      	    *p_start = child3->valueint;
      	
      	    //文件请求个数
      	    cJSON *child4 = cJSON_GetObjectItem(root, "count");
      	    if(NULL == child4)
      	    {
      	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
      	        ret = -1;
      	        goto END;
      	    }
      	
      	    *p_count = child4->valueint;
      	
      	END:
      	    if(root != NULL)
      	    {
      	        cJSON_Delete(root);//删除json对象
      	        root = NULL;
      	    }
      	
      	    return ret;
      	}
    

获取用户文件个数

  • 数据库查询操作 sprintf(sql_cmd, “select count from user_file_count where user=”%s"", user);

  • 将结果封装进tmp int ret2 = process_result_one(conn, sql_cmd, tmp);

    		//获取用户文件个数
    		void get_user_files_count(char *user, int ret)
    		{
    		    char sql_cmd[SQL_MAX_LEN] = {0};
    		    MYSQL *conn = NULL;
    		    long line = 0;
    		
    		    //connect the database
    		    conn = msql_conn(mysql_user, mysql_pwd, mysql_db);
    		    if (conn == NULL)
    		    {
    		        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "msql_conn err\n");
    		        goto END;
    		    }
    		
    		    //设置数据库编码,主要处理中文编码问题
    		    mysql_query(conn, "set names utf8");
    		
    		    sprintf(sql_cmd, "select count from user_file_count where user=\"%s\"", user);
    		    char tmp[512] = {0};
    		    //返回值: 0成功并保存记录集,1没有记录集,2有记录集但是没有保存,-1失败
    		    int ret2 = process_result_one(conn, sql_cmd, tmp); //指向sql语句
    		    if(ret2 != 0)
    		    {
    		        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "%s 操作失败\n", sql_cmd);
    		        goto END;
    		    }
    		
    		    line = atol(tmp); //字符串转长整形
    		
    		END:
    		    if(conn != NULL)
    		    {
    		        mysql_close(conn);
    		    }
    		
    		    LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "line = %ld\n", line);
    		
    		    //给前端反馈的信息
    		    return_login_status(line, ret);
    		}
    

    获取用户文件列表

  • get_user_filelist(char *cmd, char *user, int start, int count)需要参数cmd,user,start,count(这两个参数在前端设置好)

      - cmd为normal 
      普通查询只做了物理分页,==limit %d, %d", user, start, count==
       
      		    if(strcmp(cmd, "normal") == 0) //获取用户文件信息
      		    {
      		        //sql语句
      		        sprintf(sql_cmd, "select user_file_list.*, file_info.url, file_info.size, file_info.type from file_info, user_file_list where user = '%s' and file_info.md5 = user_file_list.md5 limit %d, %d", user, start, count);
      		    }	
      	
      - cmd为pvasc
      升序查询按照pv排序同时做了物理分页,==order by pv asc limit %d, %d", user, start, count)==
      		
      			 else if(strcmp(cmd, "pvasc") == 0) //按下载量升序
      			    {
      			        //sql语句
      			        sprintf(sql_cmd, "select user_file_list.*, file_info.url, file_info.size, file_info.type from file_info, user_file_list where user = '%s' and file_info.md5 = user_file_list.md5  order by pv asc limit %d, %d", user, start, count);
      			    }
      			
      -  cmd为pvdesc
      降序查询按照pv排序同时做了物理分页,==order by pv desc limit %d, %d", user, start, count==
      
      			 else if(strcmp(cmd, "pvdesc") == 0) //按下载量降序
      			    {
      			        //sql语句
      			        sprintf(sql_cmd, "select user_file_list.*, file_info.url, file_info.size, file_info.type from file_info, user_file_list where user = '%s' and file_info.md5 = user_file_list.md5 order by pv desc limit %d, %d", user, start, count);
      			    }
    
  • 进行查询 if (mysql_query(conn, sql_cmd) != 0)

  • 生成结果集 res_set = mysql_store_result(conn);/生成结果集/

  • 对结果集进行处理

    • 数据库的查询结果是一行行的,游标依次往下拿到每一个字段的值,封装进jason对象 cJSON_AddItemToArray(array, item);
    • 再封装进数组cJSON_AddItemToObject(root, “files”, array)代表所有文件的列表,
    • 再将该数组封装进root根对象转为字符串发送前端
      int get_user_filelist(char *cmd, char *user, int start, int count)
      {
          int ret = 0;
          char sql_cmd[SQL_MAX_LEN] = {0};
          MYSQL *conn = NULL;
          cJSON *root = NULL;
          cJSON *array =NULL;
          char *out = NULL;
          char *out2 = NULL;
          MYSQL_RES *res_set = NULL;
      
          //connect the database
          conn = msql_conn(mysql_user, mysql_pwd, mysql_db);
          if (conn == NULL)
          {
              LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "msql_conn err\n");
              ret = -1;
              goto END;
          }
      
          //设置数据库编码,主要处理中文编码问题
          mysql_query(conn, "set names utf8");
      
          //多表指定行范围查询
          if(strcmp(cmd, "normal") == 0) //获取用户文件信息
          {
              //sql语句
              sprintf(sql_cmd, "select user_file_list.*, file_info.url, file_info.size, file_info.type from file_info, user_file_list where user = '%s' and file_info.md5 = user_file_list.md5 limit %d, %d", user, start, count);
          }
          else if(strcmp(cmd, "pvasc") == 0) //按下载量升序
          {
              //sql语句
              sprintf(sql_cmd, "select user_file_list.*, file_info.url, file_info.size, file_info.type from file_info, user_file_list where user = '%s' and file_info.md5 = user_file_list.md5  order by pv asc limit %d, %d", user, start, count);
          }
          else if(strcmp(cmd, "pvdesc") == 0) //按下载量降序
          {
              //sql语句
              sprintf(sql_cmd, "select user_file_list.*, file_info.url, file_info.size, file_info.type from file_info, user_file_list where user = '%s' and file_info.md5 = user_file_list.md5 order by pv desc limit %d, %d", user, start, count);
          }
      
          LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "%s 在操作\n", sql_cmd);
      
          if (mysql_query(conn, sql_cmd) != 0)
          {
              LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "%s 操作失败:%s\n", sql_cmd, mysql_error(conn));
              ret = -1;
              goto END;
          }
      
          res_set = mysql_store_result(conn);/*生成结果集*/
          if (res_set == NULL)
          {
              LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "smysql_store_result error: %s!\n", mysql_error(conn));
              ret = -1;
              goto END;
          }
      
          ulong line = 0;
          //mysql_num_rows接受由mysql_store_result返回的结果结构集,并返回结构集中的行数
          line = mysql_num_rows(res_set);
          if (line == 0)//没有结果
          {
              LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "mysql_num_rows(res_set) failed:%s\n", mysql_error(conn));
              ret = -1;
              goto END;
          }
      
          MYSQL_ROW row;
      
          root = cJSON_CreateObject();
          array = cJSON_CreateArray();
          // mysql_fetch_row从使用mysql_store_result得到的结果结构中提取一行,并把它放到一个行结构中。
          // 当数据用完或发生错误时返回NULL.
          while ((row = mysql_fetch_row(res_set)) != NULL)
          {
               //array[i]:
              cJSON* item = cJSON_CreateObject();
      
              //mysql_num_fields获取结果中列的个数
              /*for(i = 0; i < mysql_num_fields(res_set); i++)
              {
                  if(row[i] != NULL)
                  {
      
                  }
              }*/
      
              /*
              {
              "user": "yoyo",
              "md5": "e8ea6031b779ac26c319ddf949ad9d8d",
              "time": "2017-02-26 21:35:25",
              "filename": "test.mp4",
              "share_status": 0,
              "pv": 0,
              "url": "http://192.168.31.109:80/group1/M00/00/00/wKgfbViy2Z2AJ-FTAaM3As-g3Z0782.mp4",
              "size": 27473666,
               "type": "mp4"
              }
      
              */
              //-- user	文件所属用户
              if(row[0] != NULL)
              {
                  cJSON_AddStringToObject(item, "user", row[0]);
              }
      
              //-- md5 文件md5
              if(row[1] != NULL)
              {
                  cJSON_AddStringToObject(item, "md5", row[1]);
              }
      
              //-- createtime 文件创建时间
              if(row[2] != NULL)
              {
                  cJSON_AddStringToObject(item, "time", row[2]);
              }
      
              //-- filename 文件名字
              if(row[3] != NULL)
              {
                  cJSON_AddStringToObject(item, "filename", row[3]);
              }
      
              //-- shared_status 共享状态, 0为没有共享, 1为共享
              if(row[4] != NULL)
              {
                  cJSON_AddNumberToObject(item, "share_status", atoi( row[4] ));
              }
      
              //-- pv 文件下载量,默认值为0,下载一次加1
              if(row[5] != NULL)
              {
                  cJSON_AddNumberToObject(item, "pv", atol( row[5] ));
              }
      
              //-- url 文件url
              if(row[6] != NULL)
              {
                  cJSON_AddStringToObject(item, "url", row[6]);
              }
      
              //-- size 文件大小, 以字节为单位
              if(row[7] != NULL)
              {
                  cJSON_AddNumberToObject(item, "size", atol( row[7] ));
              }
      
              //-- type 文件类型: png, zip, mp4……
              if(row[8] != NULL)
              {
                  cJSON_AddStringToObject(item, "type", row[8]);
              }
      
              cJSON_AddItemToArray(array, item);
          }
      
          cJSON_AddItemToObject(root, "files", array);
      
          out = cJSON_Print(root);
      
          LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "%s\n", out);
      
      END:
          if(ret == 0)
          {
              printf("%s", out); //给前端反馈信息
          }
          else
          {   //失败
              /*
              获取用户文件列表:
                  成功:文件列表json
                  失败:{"code": "015"}
              */
              out2 = NULL;
              out2 = return_status("015");
          }
          if(out2 != NULL)
          {
              printf(out2); //给前端反馈错误码
              free(out2);
          }
      
          if(res_set != NULL)
          {
              //完成所有对数据的操作后,调用mysql_free_result来善后处理
              mysql_free_result(res_set);
          }
      
          if(conn != NULL)
          {
              mysql_close(conn);
          }
      
          if(root != NULL)
          {
              cJSON_Delete(root);
          }
      
          if(out != NULL)
          {
              free(out);
          }
      
      
          return ret;
      }
    

源码

	/**
	 * @file myfiles_cgi.c
	 * @brief  用户列表展示CGI程序
	 * @author Mike
	 * @version 2.0
	 * @date 2017年2月27日
	 */
	
	#include "fcgi_config.h"
	#include "fcgi_stdio.h"
	#include <stdio.h>
	#include <stdlib.h>
	#include <string.h>
	#include "make_log.h" //日志头文件
	#include "util_cgi.h"
	#include "deal_mysql.h"
	#include "cfg.h"
	#include "cJSON.h"
	#include <sys/time.h>
	
	#define MYFILES_LOG_MODULE       "cgi"
	#define MYFILES_LOG_PROC         "myfiles"
	
	//mysql 数据库配置信息 用户名, 密码, 数据库名称
	static char mysql_user[128] = {0};
	static char mysql_pwd[128] = {0};
	static char mysql_db[128] = {0};
	
	//redis 服务器ip、端口
	//static char redis_ip[30] = {0};
	//static char redis_port[10] = {0};
	
	//读取配置信息
	void read_cfg()
	{
	    //读取mysql数据库配置信息
	    get_cfg_value(CFG_PATH, "mysql", "user", mysql_user);
	    get_cfg_value(CFG_PATH, "mysql", "password", mysql_pwd);
	    get_cfg_value(CFG_PATH, "mysql", "database", mysql_db);
	    LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "mysql:[user=%s,pwd=%s,database=%s]", mysql_user, mysql_pwd, mysql_db);
	
	    //读取redis配置信息
	    //get_cfg_value(CFG_PATH, "redis", "ip", redis_ip);
	    //get_cfg_value(CFG_PATH, "redis", "port", redis_port);
	    //LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "redis:[ip=%s,port=%s]\n", redis_ip, redis_port);
	}
	
	
	//解析的json包, 登陆token
	int get_count_json_info(char *buf, char *user, char *token)
	{
	    int ret = 0;
	
	    /*json数据如下
	    {
	        "token": "9e894efc0b2a898a82765d0a7f2c94cb",
	        user:xxxx
	    }
	    */
	
	    //解析json包
	    //解析一个json字符串为cJSON对象
	    cJSON * root = cJSON_Parse(buf);
	    if(NULL == root)
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_Parse err\n");
	        ret = -1;
	        goto END;
	    }
	
	    //返回指定字符串对应的json对象
	    //用户
	    cJSON *child1 = cJSON_GetObjectItem(root, "user");
	    if(NULL == child1)
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
	        ret = -1;
	        goto END;
	    }
	
	    //LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "child1->valuestring = %s\n", child1->valuestring);
	    strcpy(user, child1->valuestring); //拷贝内容
	
	    //登陆token
	    cJSON *child2 = cJSON_GetObjectItem(root, "token");
	    if(NULL == child2)
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
	        ret = -1;
	        goto END;
	    }
	
	    //LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "child2->valuestring = %s\n", child2->valuestring);
	    strcpy(token, child2->valuestring); //拷贝内容
	
	END:
	    if(root != NULL)
	    {
	        cJSON_Delete(root);//删除json对象
	        root = NULL;
	    }
	
	    return ret;
	}
	
	//返回前端情况
	void return_login_status(long num, int token_flag)
	{
	
	    char *out = NULL;
	    char *token;
	    char num_buf[128] = {0};
	
	    if(token_flag == 0)
	    {
	        token = "110"; //成功
	    }
	    else
	    {
	        token = "111"; //失败
	    }
	
	    //数字
	    sprintf(num_buf, "%ld", num);
	
	    cJSON *root = cJSON_CreateObject();  //创建json项目
	    cJSON_AddStringToObject(root, "num", num_buf);// {"num":"1111"}
	    cJSON_AddStringToObject(root, "code", token);// {"code":"110"}
	    out = cJSON_Print(root);//cJSON to string(char *)
	
	    cJSON_Delete(root);
	
	    if(out != NULL)
	    {
	        printf(out); //给前端反馈信息
	        free(out); //记得释放
	    }
	}
	
	//获取用户文件个数
	void get_user_files_count(char *user, int ret)
	{
	    char sql_cmd[SQL_MAX_LEN] = {0};
	    MYSQL *conn = NULL;
	    long line = 0;
	
	    //connect the database
	    conn = msql_conn(mysql_user, mysql_pwd, mysql_db);
	    if (conn == NULL)
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "msql_conn err\n");
	        goto END;
	    }
	
	    //设置数据库编码,主要处理中文编码问题
	    mysql_query(conn, "set names utf8");
	
	    sprintf(sql_cmd, "select count from user_file_count where user=\"%s\"", user);
	    char tmp[512] = {0};
	    //返回值: 0成功并保存记录集,1没有记录集,2有记录集但是没有保存,-1失败
	    int ret2 = process_result_one(conn, sql_cmd, tmp); //指向sql语句
	    if(ret2 != 0)
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "%s 操作失败\n", sql_cmd);
	        goto END;
	    }
	
	    line = atol(tmp); //字符串转长整形
	
	END:
	    if(conn != NULL)
	    {
	        mysql_close(conn);
	    }
	
	    LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "line = %ld\n", line);
	
	    //给前端反馈的信息
	    return_login_status(line, ret);
	}
	
	//解析的json包
	int get_fileslist_json_info(char *buf, char *user, char *token, int *p_start, int *p_count)
	{
	    int ret = 0;
	
	    /*json数据如下
	    {
	        "user": "yoyo"
	        "token": xxxx
	        "start": 0
	        "count": 10
	    }
	    */
	
	    //解析json包
	    //解析一个json字符串为cJSON对象
	    cJSON * root = cJSON_Parse(buf);
	    if(NULL == root)
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_Parse err\n");
	        ret = -1;
	        goto END;
	    }
	
	    //返回指定字符串对应的json对象
	    //用户
	    cJSON *child1 = cJSON_GetObjectItem(root, "user");
	    if(NULL == child1)
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
	        ret = -1;
	        goto END;
	    }
	
	    //LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "child1->valuestring = %s\n", child1->valuestring);
	    strcpy(user, child1->valuestring); //拷贝内容
	
	    //token
	    cJSON *child2 = cJSON_GetObjectItem(root, "token");
	    if(NULL == child2)
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
	        ret = -1;
	        goto END;
	    }
	
	    strcpy(token, child2->valuestring); //拷贝内容
	
	    //文件起点
	    cJSON *child3 = cJSON_GetObjectItem(root, "start");
	    if(NULL == child3)
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
	        ret = -1;
	        goto END;
	    }
	
	    *p_start = child3->valueint;
	
	    //文件请求个数
	    cJSON *child4 = cJSON_GetObjectItem(root, "count");
	    if(NULL == child4)
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
	        ret = -1;
	        goto END;
	    }
	
	    *p_count = child4->valueint;
	
	END:
	    if(root != NULL)
	    {
	        cJSON_Delete(root);//删除json对象
	        root = NULL;
	    }
	
	    return ret;
	}
	
	//获取用户文件列表
	//获取用户文件信息 127.0.0.1:80/myfiles&cmd=normal
	//按下载量升序 127.0.0.1:80/myfiles?cmd=pvasc
	//按下载量降序127.0.0.1:80/myfiles?cmd=pvdesc
	int get_user_filelist(char *cmd, char *user, int start, int count)
	{
	    int ret = 0;
	    char sql_cmd[SQL_MAX_LEN] = {0};
	    MYSQL *conn = NULL;
	    cJSON *root = NULL;
	    cJSON *array =NULL;
	    char *out = NULL;
	    char *out2 = NULL;
	    MYSQL_RES *res_set = NULL;
	
	    //connect the database
	    conn = msql_conn(mysql_user, mysql_pwd, mysql_db);
	    if (conn == NULL)
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "msql_conn err\n");
	        ret = -1;
	        goto END;
	    }
	
	    //设置数据库编码,主要处理中文编码问题
	    mysql_query(conn, "set names utf8");
	
	    //多表指定行范围查询
	    if(strcmp(cmd, "normal") == 0) //获取用户文件信息
	    {
	        //sql语句
	        sprintf(sql_cmd, "select user_file_list.*, file_info.url, file_info.size, file_info.type from file_info, user_file_list where user = '%s' and file_info.md5 = user_file_list.md5 limit %d, %d", user, start, count);
	    }
	    else if(strcmp(cmd, "pvasc") == 0) //按下载量升序
	    {
	        //sql语句
	        sprintf(sql_cmd, "select user_file_list.*, file_info.url, file_info.size, file_info.type from file_info, user_file_list where user = '%s' and file_info.md5 = user_file_list.md5  order by pv asc limit %d, %d", user, start, count);
	    }
	    else if(strcmp(cmd, "pvdesc") == 0) //按下载量降序
	    {
	        //sql语句
	        sprintf(sql_cmd, "select user_file_list.*, file_info.url, file_info.size, file_info.type from file_info, user_file_list where user = '%s' and file_info.md5 = user_file_list.md5 order by pv desc limit %d, %d", user, start, count);
	    }
	
	    LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "%s 在操作\n", sql_cmd);
	
	    if (mysql_query(conn, sql_cmd) != 0)
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "%s 操作失败:%s\n", sql_cmd, mysql_error(conn));
	        ret = -1;
	        goto END;
	    }
	
	    res_set = mysql_store_result(conn);/*生成结果集*/
	    if (res_set == NULL)
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "smysql_store_result error: %s!\n", mysql_error(conn));
	        ret = -1;
	        goto END;
	    }
	
	    ulong line = 0;
	    //mysql_num_rows接受由mysql_store_result返回的结果结构集,并返回结构集中的行数
	    line = mysql_num_rows(res_set);
	    if (line == 0)//没有结果
	    {
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "mysql_num_rows(res_set) failed:%s\n", mysql_error(conn));
	        ret = -1;
	        goto END;
	    }
	
	    MYSQL_ROW row;
	
	    root = cJSON_CreateObject();
	    array = cJSON_CreateArray();
	    // mysql_fetch_row从使用mysql_store_result得到的结果结构中提取一行,并把它放到一个行结构中。
	    // 当数据用完或发生错误时返回NULL.
	    while ((row = mysql_fetch_row(res_set)) != NULL)
	    {
	         //array[i]:
	        cJSON* item = cJSON_CreateObject();
	
	        //mysql_num_fields获取结果中列的个数
	        /*for(i = 0; i < mysql_num_fields(res_set); i++)
	        {
	            if(row[i] != NULL)
	            {
	
	            }
	        }*/
	
	        /*
	        {
	        "user": "yoyo",
	        "md5": "e8ea6031b779ac26c319ddf949ad9d8d",
	        "time": "2017-02-26 21:35:25",
	        "filename": "test.mp4",
	        "share_status": 0,
	        "pv": 0,
	        "url": "http://192.168.31.109:80/group1/M00/00/00/wKgfbViy2Z2AJ-FTAaM3As-g3Z0782.mp4",
	        "size": 27473666,
	         "type": "mp4"
	        }
	
	        */
	        //-- user	文件所属用户
	        if(row[0] != NULL)
	        {
	            cJSON_AddStringToObject(item, "user", row[0]);
	        }
	
	        //-- md5 文件md5
	        if(row[1] != NULL)
	        {
	            cJSON_AddStringToObject(item, "md5", row[1]);
	        }
	
	        //-- createtime 文件创建时间
	        if(row[2] != NULL)
	        {
	            cJSON_AddStringToObject(item, "time", row[2]);
	        }
	
	        //-- filename 文件名字
	        if(row[3] != NULL)
	        {
	            cJSON_AddStringToObject(item, "filename", row[3]);
	        }
	
	        //-- shared_status 共享状态, 0为没有共享, 1为共享
	        if(row[4] != NULL)
	        {
	            cJSON_AddNumberToObject(item, "share_status", atoi( row[4] ));
	        }
	
	        //-- pv 文件下载量,默认值为0,下载一次加1
	        if(row[5] != NULL)
	        {
	            cJSON_AddNumberToObject(item, "pv", atol( row[5] ));
	        }
	
	        //-- url 文件url
	        if(row[6] != NULL)
	        {
	            cJSON_AddStringToObject(item, "url", row[6]);
	        }
	
	        //-- size 文件大小, 以字节为单位
	        if(row[7] != NULL)
	        {
	            cJSON_AddNumberToObject(item, "size", atol( row[7] ));
	        }
	
	        //-- type 文件类型: png, zip, mp4……
	        if(row[8] != NULL)
	        {
	            cJSON_AddStringToObject(item, "type", row[8]);
	        }
	
	        cJSON_AddItemToArray(array, item);
	    }
	
	    cJSON_AddItemToObject(root, "files", array);
	
	    out = cJSON_Print(root);
	
	    LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "%s\n", out);
	
	END:
	    if(ret == 0)
	    {
	        printf("%s", out); //给前端反馈信息
	    }
	    else
	    {   //失败
	        /*
	        获取用户文件列表:
	            成功:文件列表json
	            失败:{"code": "015"}
	        */
	        out2 = NULL;
	        out2 = return_status("015");
	    }
	    if(out2 != NULL)
	    {
	        printf(out2); //给前端反馈错误码
	        free(out2);
	    }
	
	    if(res_set != NULL)
	    {
	        //完成所有对数据的操作后,调用mysql_free_result来善后处理
	        mysql_free_result(res_set);
	    }
	
	    if(conn != NULL)
	    {
	        mysql_close(conn);
	    }
	
	    if(root != NULL)
	    {
	        cJSON_Delete(root);
	    }
	
	    if(out != NULL)
	    {
	        free(out);
	    }
	
	
	    return ret;
	}
	
	int main()
	{
	    //count 获取用户文件个数
	    //display 获取用户文件信息,展示到前端
	    char cmd[20];
	    char user[USER_NAME_LEN];
	    char token[TOKEN_LEN];
	
	     //读取数据库配置信息
	    read_cfg();
	
	    //阻塞等待用户连接
	    while (FCGI_Accept() >= 0)
	    {
	
	        // 获取URL地址 "?" 后面的内容
	        char *query = getenv("QUERY_STRING");
	
	        //解析命令
	        query_parse_key_value(query, "cmd", cmd, NULL);
	        LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "cmd = %s\n", cmd);
	
	        char *contentLength = getenv("CONTENT_LENGTH");
	        int len;
	
	        printf("Content-type: text/html\r\n\r\n");
	
	        if( contentLength == NULL )
	        {
	            len = 0;
	        }
	        else
	        {
	            len = atoi(contentLength); //字符串转整型
	        }
	
	        if (len <= 0)
	        {
	            printf("No data from standard input.<p>\n");
	            LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "len = 0, No data from standard input\n");
	        }
	        else
	        {
	            char buf[4*1024] = {0};
	            int ret = 0;
	            ret = fread(buf, 1, len, stdin); //从标准输入(web服务器)读取内容
	            if(ret == 0)
	            {
	                LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "fread(buf, 1, len, stdin) err\n");
	                continue;
	            }
	
	            LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "buf = %s\n", buf);
	
	            if (strcmp(cmd, "count") == 0) //count 获取用户文件个数
	            {
	                get_count_json_info(buf, user, token); //通过json包获取用户名, token
	
	                //验证登陆token,成功返回0,失败-1
	                ret = verify_token(user, token); //util_cgi.h
	
	                get_user_files_count(user, ret); //获取用户文件个数
	
	            }
	            //获取用户文件信息 127.0.0.1:80/myfiles&cmd=normal
	            //按下载量升序 127.0.0.1:80/myfiles?cmd=pvasc
	            //按下载量降序127.0.0.1:80/myfiles?cmd=pvdesc
	            else
	            {
	                int start; //文件起点
	                int count; //文件个数
	                get_fileslist_json_info(buf, user, token, &start, &count); //通过json包获取信息
	                LOG(MYFILES_LOG_MODULE, MYFILES_LOG_PROC, "user = %s, token = %s, start = %d, count = %d\n", user, token, start, count);
	
	                //验证登陆token,成功返回0,失败-1
	                ret = verify_token(user, token); //util_cgi.h
	                if(ret == 0)
	                {
	                     get_user_filelist(cmd, user, start, count); //获取用户文件列表
	                }
	                else
	                {
	                    char *out = return_status("111"); //token验证失败错误码
	                    if(out != NULL)
	                    {
	                        printf(out); //给前端反馈错误码
	                        free(out);
	                    }
	                }
	
	            }
	
	        }
	
	    }
	
	    return 0;
	}

共享文件列表

业务逻辑,点击QT界面的共享列表,会显示背当前用户共享的文件,且是普通排序

  • 点击图标会显示取消分享,属性
  • 点击空白处会选项显示排行榜

共享文件列表主要涉及的是file_info和share_file_list两张表查询

main

  • cmd为count,代表获取该用户共享出去的文件个数,只返回给前端共享了的文件个数

       if (strcmp(cmd, "count") == 0) //count 获取用户文件个数
              {
                  get_share_files_count(); //获取共享文件个数
              }
    
  • 解析jason包拿到拿到count,start

  • 如果cmd为normal,则就按照查询顺序显示共享文件列表

  • 如果cmd为pvdesc,则将查询结果按照pv字段降序排列显示共享文件列表

  • 如果cmd为pvasc,则将查询结果按照pv字段升序排列显示为共享文件列表

获取共享文件个数

  • get_share_files_count(),当cmd为count,则只需要查询共享文件个数

  • 从user_file_count查询处用户的共享文件个数

		void get_share_files_count()
		{
		    char sql_cmd[SQL_MAX_LEN] = {0};
		    MYSQL *conn = NULL;
		    long line = 0;
		
	    //connect the database
	    conn = msql_conn(mysql_user, mysql_pwd, mysql_db);
	    if (conn == NULL)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "msql_conn err\n");
	        goto END;
	    }
	
	    //设置数据库编码,主要处理中文编码问题
	    mysql_query(conn, "set names utf8");
	
	    sprintf(sql_cmd, "select count from user_file_count where user=\"%s\"", "xxx_share_xxx_file_xxx_list_xxx_count_xxx");
	    char tmp[512] = {0};
	    int ret2 = process_result_one(conn, sql_cmd, tmp); //指向sql语句
	    if(ret2 != 0)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "%s 操作失败\n", sql_cmd);
	        goto END;
	    }
	
	    line = atol(tmp); //字符串转长整形
	
	END:
	    if(conn != NULL)
	    {
	        mysql_close(conn);
	    }
	
	    LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "line = %ld\n", line);
	    printf("%ld", line); //给前端反馈的信息
	}

前端分页请求包

  • get_fileslist_json_info

  • 这个包是前端发送的post数据,封装的是物理分页的信息,然后再根据URL上的指令去做业务逻辑判断

  • 解析包拿到start,count

      //解析的json包
      		int get_fileslist_json_info(char *buf, int *p_start, int *p_count)
      		{
      		    int ret = 0;
      
          /*json数据如下
          {
              "start": 0
              "count": 10
          }
          */
      
          //解析json包
          //解析一个json字符串为cJSON对象
          cJSON * root = cJSON_Parse(buf);
          if(NULL == root)
          {
              LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "cJSON_Parse err\n");
              ret = -1;
              goto END;
          }
      
          //文件起点
          cJSON *child2 = cJSON_GetObjectItem(root, "start");
          if(NULL == child2)
          {
              LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
              ret = -1;
              goto END;
          }
      
          *p_start = child2->valueint;
      
          //文件请求个数
          cJSON *child3 = cJSON_GetObjectItem(root, "count");
          if(NULL == child3)
          {
              LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
              ret = -1;
              goto END;
          }
      
          *p_count = child3->valueint;
      
      END:
          if(root != NULL)
          {
              cJSON_Delete(root);//删除json对象
              root = NULL;
          }
      
          return ret;
      }
    

获得普通共享文件列表

  • get_share_filelist(int start, int count)

  • 查出share_file_list所有记录,同时根据md5查file_info表部分文件信息并进行物理分页

  • 从结果集中将记录进行一行行封装成对象;将封装好的对象加入数组;将数组加到跟对象root,将root转为字符串输出

      //获取共享文件列表
      //获取用户文件信息 127.0.0.1:80/sharefiles&cmd=normal
      int get_share_filelist(int start, int count)
      {
          int ret = 0;
          char sql_cmd[SQL_MAX_LEN] = {0};
          MYSQL *conn = NULL;
          cJSON *root = NULL;
          cJSON *array =NULL;
          char *out = NULL;
          char *out2 = NULL;
          MYSQL_RES *res_set = NULL;
      
          //connect the database
          conn = msql_conn(mysql_user, mysql_pwd, mysql_db);
          if (conn == NULL)
          {
              LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "msql_conn err\n");
              ret = -1;
              goto END;
          }
      
          //设置数据库编码,主要处理中文编码问题
          mysql_query(conn, "set names utf8");
      
      
          //sql语句
          sprintf(sql_cmd, "select share_file_list.*, file_info.url, file_info.size, file_info.type from file_info, share_file_list where file_info.md5 = share_file_list.md5 limit %d, %d", start, count);
      
          LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "%s 在操作\n", sql_cmd);
      
          if (mysql_query(conn, sql_cmd) != 0)
          {
              LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "%s 操作失败: %s\n", sql_cmd, mysql_error(conn));
              ret = -1;
              goto END;
          }
      
          res_set = mysql_store_result(conn);/*生成结果集*/
          if (res_set == NULL)
          {
              LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "smysql_store_result error!\n");
              ret = -1;
              goto END;
          }
      
          ulong line = 0;
          //mysql_num_rows接受由mysql_store_result返回的结果结构集,并返回结构集中的行数
          line = mysql_num_rows(res_set);
          if (line == 0)
          {
              LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "mysql_num_rows(res_set) failed\n");
              ret = -1;
              goto END;
          }
      
          MYSQL_ROW row;
      
          root = cJSON_CreateObject();
          array = cJSON_CreateArray();
          // mysql_fetch_row从使用mysql_store_result得到的结果结构中提取一行,并把它放到一个行结构中。
          // 当数据用完或发生错误时返回NULL.
          while ((row = mysql_fetch_row(res_set)) != NULL)
          {
               //array[i]:
              cJSON* item = cJSON_CreateObject();
      
              //mysql_num_fields获取结果中列的个数
              /*for(i = 0; i < mysql_num_fields(res_set); i++)
              {
                  if(row[i] != NULL)
                  {
      
                  }
              }*/
      
              /*
              {
              "user": "yoyo",
              "md5": "e8ea6031b779ac26c319ddf949ad9d8d",
              "time": "2017-02-26 21:35:25",
              "filename": "test.mp4",
              "share_status": 1,
              "pv": 0,
              "url": "http://192.168.31.109:80/group1/M00/00/00/wKgfbViy2Z2AJ-FTAaM3As-g3Z0782.mp4",
              "size": 27473666,
               "type": "mp4"
              }
      
              */
              //-- user	文件所属用户
              if(row[0] != NULL)
              {
                  cJSON_AddStringToObject(item, "user", row[0]);
              }
      
              //-- md5 文件md5
              if(row[1] != NULL)
              {
                  cJSON_AddStringToObject(item, "md5", row[1]);
              }
      
              //-- createtime 文件创建时间
              if(row[2] != NULL)
              {
                  cJSON_AddStringToObject(item, "time", row[2]);
              }
      
              //-- filename 文件名字
              if(row[3] != NULL)
              {
                  cJSON_AddStringToObject(item, "filename", row[3]);
              }
      
              //-- shared_status 共享状态, 0为没有共享, 1为共享
              cJSON_AddNumberToObject(item, "share_status", 1);
      
      
              //-- pv 文件下载量,默认值为0,下载一次加1
              if(row[4] != NULL)
              {
                  cJSON_AddNumberToObject(item, "pv", atol( row[4] ));
              }
      
              //-- url 文件url
              if(row[5] != NULL)
              {
                  cJSON_AddStringToObject(item, "url", row[5]);
              }
      
              //-- size 文件大小, 以字节为单位
              if(row[6] != NULL)
              {
                  cJSON_AddNumberToObject(item, "size", atol( row[6] ));
              }
      
              //-- type 文件类型: png, zip, mp4……
              if(row[7] != NULL)
              {
                  cJSON_AddStringToObject(item, "type", row[7]);
              }
      
              cJSON_AddItemToArray(array, item);
          }
      
          cJSON_AddItemToObject(root, "files", array);
      
          out = cJSON_Print(root);
      
          LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "%s\n", out);
      
      END:
          if(ret == 0)
          {
              printf("%s", out); //给前端反馈信息
          }
          else
          {   //失败
              out2 = NULL;
              out2 = return_status("015");
          }
          if(out2 != NULL)
          {
              printf(out2); //给前端反馈错误码
              free(out2);
          }
      
          if(res_set != NULL)
          {
              //完成所有对数据的操作后,调用mysql_free_result来善后处理
              mysql_free_result(res_set);
          }
      
          if(conn != NULL)
          {
              mysql_close(conn);
          }
      
          if(root != NULL)
          {
              cJSON_Delete(root);
          }
      
          if(out != NULL)
          {
              free(out);
          }
      
          return ret;
      }
    

共享文件排行榜

  • 操作redis “FILE_NAME_HASH”和“FILE_PUBLIC_ZSET”两张表和MySQL“share_file_list”,完成redis和MySQL数据交互
  • int get_ranking_filelist(int start, int count)
  • 拿到mysql中共享文件的数量,拿到redis中的共享文件的数量进行比较
    • 不相等,更新redis数据,删除redis中所有数据( FILE_PUBLIC_ZSET,FILE_NAME_HASH) ;再将mysql中的数据导入到mysql:查出share_file_list中md5,filename和pv字段,游标提取结果集每一行(md5+filename组成fileid和pv字段作为score一起添加到zset;将组合的fileid作为fileld,filename作为value添加到hash表)
  • 将zset按照score降序排序,其中排序有分页参数start,end;
  • 将排序后的集合从FILE_NAME_HASH取出filename,从FILE_PUBLIC_ZSET取出pv字段封装成对象;再将数据封装成对象转字符串后发送给前端 printf("%s", out),会在QT界面点击排行榜时候显示

源码

	/**
	 * @file sharefiles_cgi.c
	 * @brief  共享文件列表展示CGI程序
	 * @author Mike
	 * @version 2.0
	 * @date 2017年3月7日21:46:57
	 */
	
	#include "fcgi_config.h"
	#include "fcgi_stdio.h"
	#include <stdio.h>
	#include <stdlib.h>
	#include <string.h>
	#include "make_log.h" //日志头文件
	#include "util_cgi.h"
	#include "deal_mysql.h"
	#include "redis_keys.h"
	#include "redis_op.h"
	#include "cfg.h"
	#include "cJSON.h"
	#include <sys/time.h>
	
	#define SHAREFILES_LOG_MODULE       "cgi"
	#define SHAREFILES_LOG_PROC         "sharefiles"
	
	//mysql 数据库配置信息 用户名, 密码, 数据库名称
	static char mysql_user[128] = {0};
	static char mysql_pwd[128] = {0};
	static char mysql_db[128] = {0};
	
	//redis 服务器ip、端口
	static char redis_ip[30] = {0};
	static char redis_port[10] = {0};
	
	//读取配置信息
	void read_cfg()
	{
	    //读取mysql数据库配置信息
	    get_cfg_value(CFG_PATH, "mysql", "user", mysql_user);
	    get_cfg_value(CFG_PATH, "mysql", "password", mysql_pwd);
	    get_cfg_value(CFG_PATH, "mysql", "database", mysql_db);
	    LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "mysql:[user=%s,pwd=%s,database=%s]", mysql_user, mysql_pwd, mysql_db);
	
	    //读取redis配置信息
	    get_cfg_value(CFG_PATH, "redis", "ip", redis_ip);
	    get_cfg_value(CFG_PATH, "redis", "port", redis_port);
	    LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "redis:[ip=%s,port=%s]\n", redis_ip, redis_port);
	}
	
	//获取共享文件个数
	void get_share_files_count()
	{
	    char sql_cmd[SQL_MAX_LEN] = {0};
	    MYSQL *conn = NULL;
	    long line = 0;
	
	    //connect the database
	    conn = msql_conn(mysql_user, mysql_pwd, mysql_db);
	    if (conn == NULL)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "msql_conn err\n");
	        goto END;
	    }
	
	    //设置数据库编码,主要处理中文编码问题
	    mysql_query(conn, "set names utf8");
	
	    sprintf(sql_cmd, "select count from user_file_count where user=\"%s\"", "xxx_share_xxx_file_xxx_list_xxx_count_xxx");
	    char tmp[512] = {0};
	    int ret2 = process_result_one(conn, sql_cmd, tmp); //指向sql语句
	    if(ret2 != 0)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "%s 操作失败\n", sql_cmd);
	        goto END;
	    }
	
	    line = atol(tmp); //字符串转长整形
	
	END:
	    if(conn != NULL)
	    {
	        mysql_close(conn);
	    }
	
	    LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "line = %ld\n", line);
	    printf("%ld", line); //给前端反馈的信息
	}
	
	//解析的json包
	int get_fileslist_json_info(char *buf, int *p_start, int *p_count)
	{
	    int ret = 0;
	
	    /*json数据如下
	    {
	        "start": 0
	        "count": 10
	    }
	    */
	
	    //解析json包
	    //解析一个json字符串为cJSON对象
	    cJSON * root = cJSON_Parse(buf);
	    if(NULL == root)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "cJSON_Parse err\n");
	        ret = -1;
	        goto END;
	    }
	
	    //文件起点
	    cJSON *child2 = cJSON_GetObjectItem(root, "start");
	    if(NULL == child2)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
	        ret = -1;
	        goto END;
	    }
	
	    *p_start = child2->valueint;
	
	    //文件请求个数
	    cJSON *child3 = cJSON_GetObjectItem(root, "count");
	    if(NULL == child3)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "cJSON_GetObjectItem err\n");
	        ret = -1;
	        goto END;
	    }
	
	    *p_count = child3->valueint;
	
	END:
	    if(root != NULL)
	    {
	        cJSON_Delete(root);//删除json对象
	        root = NULL;
	    }
	
	    return ret;
	}
	
	//获取共享文件列表
	//获取用户文件信息 127.0.0.1:80/sharefiles&cmd=normal
	int get_share_filelist(int start, int count)
	{
	    int ret = 0;
	    char sql_cmd[SQL_MAX_LEN] = {0};
	    MYSQL *conn = NULL;
	    cJSON *root = NULL;
	    cJSON *array =NULL;
	    char *out = NULL;
	    char *out2 = NULL;
	    MYSQL_RES *res_set = NULL;
	
	    //connect the database
	    conn = msql_conn(mysql_user, mysql_pwd, mysql_db);
	    if (conn == NULL)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "msql_conn err\n");
	        ret = -1;
	        goto END;
	    }
	
	    //设置数据库编码,主要处理中文编码问题
	    mysql_query(conn, "set names utf8");
	
	
	    //sql语句
	    sprintf(sql_cmd, "select share_file_list.*, file_info.url, file_info.size, file_info.type from file_info, share_file_list where file_info.md5 = share_file_list.md5 limit %d, %d", start, count);
	
	    LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "%s 在操作\n", sql_cmd);
	
	    if (mysql_query(conn, sql_cmd) != 0)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "%s 操作失败: %s\n", sql_cmd, mysql_error(conn));
	        ret = -1;
	        goto END;
	    }
	
	    res_set = mysql_store_result(conn);/*生成结果集*/
	    if (res_set == NULL)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "smysql_store_result error!\n");
	        ret = -1;
	        goto END;
	    }
	
	    ulong line = 0;
	    //mysql_num_rows接受由mysql_store_result返回的结果结构集,并返回结构集中的行数
	    line = mysql_num_rows(res_set);
	    if (line == 0)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "mysql_num_rows(res_set) failed\n");
	        ret = -1;
	        goto END;
	    }
	
	    MYSQL_ROW row;
	
	    root = cJSON_CreateObject();
	    array = cJSON_CreateArray();
	    // mysql_fetch_row从使用mysql_store_result得到的结果结构中提取一行,并把它放到一个行结构中。
	    // 当数据用完或发生错误时返回NULL.
	    while ((row = mysql_fetch_row(res_set)) != NULL)
	    {
	         //array[i]:
	        cJSON* item = cJSON_CreateObject();
	
	        //mysql_num_fields获取结果中列的个数
	        /*for(i = 0; i < mysql_num_fields(res_set); i++)
	        {
	            if(row[i] != NULL)
	            {
	
	            }
	        }*/
	
	        /*
	        {
	        "user": "yoyo",
	        "md5": "e8ea6031b779ac26c319ddf949ad9d8d",
	        "time": "2017-02-26 21:35:25",
	        "filename": "test.mp4",
	        "share_status": 1,
	        "pv": 0,
	        "url": "http://192.168.31.109:80/group1/M00/00/00/wKgfbViy2Z2AJ-FTAaM3As-g3Z0782.mp4",
	        "size": 27473666,
	         "type": "mp4"
	        }
	
	        */
	        //-- user	文件所属用户
	        if(row[0] != NULL)
	        {
	            cJSON_AddStringToObject(item, "user", row[0]);
	        }
	
	        //-- md5 文件md5
	        if(row[1] != NULL)
	        {
	            cJSON_AddStringToObject(item, "md5", row[1]);
	        }
	
	        //-- createtime 文件创建时间
	        if(row[2] != NULL)
	        {
	            cJSON_AddStringToObject(item, "time", row[2]);
	        }
	
	        //-- filename 文件名字
	        if(row[3] != NULL)
	        {
	            cJSON_AddStringToObject(item, "filename", row[3]);
	        }
	
	        //-- shared_status 共享状态, 0为没有共享, 1为共享
	        cJSON_AddNumberToObject(item, "share_status", 1);
	
	
	        //-- pv 文件下载量,默认值为0,下载一次加1
	        if(row[4] != NULL)
	        {
	            cJSON_AddNumberToObject(item, "pv", atol( row[4] ));
	        }
	
	        //-- url 文件url
	        if(row[5] != NULL)
	        {
	            cJSON_AddStringToObject(item, "url", row[5]);
	        }
	
	        //-- size 文件大小, 以字节为单位
	        if(row[6] != NULL)
	        {
	            cJSON_AddNumberToObject(item, "size", atol( row[6] ));
	        }
	
	        //-- type 文件类型: png, zip, mp4……
	        if(row[7] != NULL)
	        {
	            cJSON_AddStringToObject(item, "type", row[7]);
	        }
	
	        cJSON_AddItemToArray(array, item);
	    }
	
	    cJSON_AddItemToObject(root, "files", array);
	
	    out = cJSON_Print(root);
	
	    LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "%s\n", out);
	
	END:
	    if(ret == 0)
	    {
	        printf("%s", out); //给前端反馈信息
	    }
	    else
	    {   //失败
	        out2 = NULL;
	        out2 = return_status("015");
	    }
	    if(out2 != NULL)
	    {
	        printf(out2); //给前端反馈错误码
	        free(out2);
	    }
	
	    if(res_set != NULL)
	    {
	        //完成所有对数据的操作后,调用mysql_free_result来善后处理
	        mysql_free_result(res_set);
	    }
	
	    if(conn != NULL)
	    {
	        mysql_close(conn);
	    }
	
	    if(root != NULL)
	    {
	        cJSON_Delete(root);
	    }
	
	    if(out != NULL)
	    {
	        free(out);
	    }
	
	    return ret;
	}
	
	//获取共享文件排行版
	//按下载量降序127.0.0.1:80/sharefiles?cmd=pvdesc
	int get_ranking_filelist(int start, int count)
	{
	    /*
	    a) mysql共享文件数量和redis共享文件数量对比,判断是否相等
	    b) 如果不相等,清空redis数据,从mysql中导入数据到redis (mysql和redis交互)
	    c) 从redis读取数据,给前端反馈相应信息
	    */
	
	    int ret = 0;
	    char sql_cmd[SQL_MAX_LEN] = {0};
	    MYSQL *conn = NULL;
	    cJSON *root = NULL;
	    RVALUES value = NULL;
	    cJSON *array =NULL;
	    char *out = NULL;
	    char *out2 = NULL;
	    char tmp[512] = {0};
	    int ret2 = 0;
	    MYSQL_RES *res_set = NULL;
	    redisContext * redis_conn = NULL;
	
	    //连接redis数据库
	    redis_conn = rop_connectdb_nopwd(redis_ip, redis_port);
	    if (redis_conn == NULL)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "redis connected error");
	        ret = -1;
	        goto END;
	    }
	
	    //connect the database
	    conn = msql_conn(mysql_user, mysql_pwd, mysql_db);
	    if (conn == NULL)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "msql_conn err\n");
	        ret = -1;
	        goto END;
	    }
	
	    //设置数据库编码,主要处理中文编码问题
	    mysql_query(conn, "set names utf8");
	
	    //===1、mysql共享文件数量
	    sprintf(sql_cmd, "select count from user_file_count where user=\"%s\"", "xxx_share_xxx_file_xxx_list_xxx_count_xxx");
	    ret2 = process_result_one(conn, sql_cmd, tmp); //指向sql语句
	    if(ret2 != 0)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "%s 操作失败\n", sql_cmd);
	        ret = -1;
	        goto END;
	    }
	
	    int sql_num = atoi(tmp); //字符串转长整形
	
	    //===2、redis共享文件数量
	    int redis_num = rop_zset_zcard(redis_conn, FILE_PUBLIC_ZSET);
	    if(redis_num == -1)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "rop_zset_zcard 操作失败\n");
	        ret = -1;
	        goto END;
	    }
	
	    LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "sql_num = %d, redis_num = %d\n", sql_num, redis_num);
	
	    //===3、mysql共享文件数量和redis共享文件数量对比,判断是否相等
	    if(redis_num != sql_num)
	    {//===4、如果不相等,清空redis数据,重新从mysql中导入数据到redis (mysql和redis交互)
	
	        //a) 清空redis有序数据
	        rop_del_key(redis_conn, FILE_PUBLIC_ZSET);
	        rop_del_key(redis_conn, FILE_NAME_HASH);
	
	        //b) 从mysql中导入数据到redis
	        //sql语句
	        strcpy(sql_cmd, "select md5, filename, pv from share_file_list order by pv desc");
	
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "%s 在操作\n", sql_cmd);
	
	        if (mysql_query(conn, sql_cmd) != 0)
	        {
	            LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "%s 操作失败: %s\n", sql_cmd, mysql_error(conn));
	            ret = -1;
	            goto END;
	        }
	
	        res_set = mysql_store_result(conn);/*生成结果集*/
	        if (res_set == NULL)
	        {
	            LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "smysql_store_result error!\n");
	            ret = -1;
	            goto END;
	        }
	
	        ulong line = 0;
	        //mysql_num_rows接受由mysql_store_result返回的结果结构集,并返回结构集中的行数
	        line = mysql_num_rows(res_set);
	        if (line == 0)
	        {
	            LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "mysql_num_rows(res_set) failed\n");
	            ret = -1;
	            goto END;
	        }
	
	         MYSQL_ROW row;
	        // mysql_fetch_row从使用mysql_store_result得到的结果结构中提取一行,并把它放到一个行结构中。
	        // 当数据用完或发生错误时返回NULL.
	        while ((row = mysql_fetch_row(res_set)) != NULL)
	        {
	            //md5, filename, pv
	            if(row[0] == NULL || row[1] == NULL || row[2] == NULL)
	            {
	                LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "mysql_fetch_row(res_set)) failed\n");
	                ret = -1;
	                goto END;
	            }
	
	            char fileid[1024] = {0};
	            sprintf(fileid, "%s%s", row[0], row[1]); //文件标示,md5+文件名
	
	            //增加有序集合成员
	            rop_zset_add(redis_conn, FILE_PUBLIC_ZSET, atoi(row[2]), fileid);
	
	            //增加hash记录
	            rop_hash_set(redis_conn, FILE_NAME_HASH, fileid, row[1]);
	        }
	    }
	
	    //===5、从redis读取数据,给前端反馈相应信息
	    //char value[count][1024];
	    value  = (RVALUES)calloc(count, VALUES_ID_SIZE); //堆区请求空间
	    if(value == NULL)
	    {
	        ret = -1;
	        goto END;
	    }
	
	    int n = 0;
	    int end = start + count - 1;//加载资源的结束位置
	    //降序获取有序集合的元素
	    ret = rop_zset_zrevrange(redis_conn, FILE_PUBLIC_ZSET, start, end, value, &n);
	    if(ret != 0)
	    {
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "rop_zset_zrevrange 操作失败\n");
	        goto END;
	    }
	
	    root = cJSON_CreateObject();
	    array = cJSON_CreateArray();
	    //遍历元素个数
	    for(int i = 0; i < n; ++i)
	    {
	        //array[i]:
	        cJSON* item = cJSON_CreateObject();
	
	        /*
	        {
	            "filename": "test.mp4",
	            "pv": 0
	        }
	        */
	
	        //-- filename 文件名字
	        char filename[1024] = {0};
	        ret = rop_hash_get(redis_conn, FILE_NAME_HASH, value[i], filename);
	        if(ret != 0)
	        {
	            LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "rop_hash_get 操作失败\n");
	            ret = -1;
	            goto END;
	        }
	        cJSON_AddStringToObject(item, "filename", filename);
	
	
	        //-- pv 文件下载量
	        int score = rop_zset_get_score(redis_conn, FILE_PUBLIC_ZSET, value[i]);
	        if(score == -1)
	        {
	            LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "rop_zset_get_score 操作失败\n");
	            ret = -1;
	            goto END;
	        }
	        cJSON_AddNumberToObject(item, "pv", score);
	
	
	        cJSON_AddItemToArray(array, item);
	
	    }
	
	    cJSON_AddItemToObject(root, "files", array);
	
	    out = cJSON_Print(root);
	
	    LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "%s\n", out);
	
	END:
	    if(ret == 0)
	    {
	        printf("%s", out); //给前端反馈信息
	    }
	    else
	    {   //失败
	        out2 = NULL;
	        out2 = return_status("015");
	    }
	    if(out2 != NULL)
	    {
	        printf(out2); //给前端反馈错误码
	        free(out2);
	    }
	
	    if(res_set != NULL)
	    {
	        //完成所有对数据的操作后,调用mysql_free_result来善后处理
	        mysql_free_result(res_set);
	    }
	
	    if(redis_conn != NULL)
	    {
	        rop_disconnect(redis_conn);
	    }
	
	    if(conn != NULL)
	    {
	        mysql_close(conn);
	    }
	
	    if(value != NULL)
	    {
	        free(value);
	    }
	
	    if(root != NULL)
	    {
	        cJSON_Delete(root);
	    }
	
	    if(out != NULL)
	    {
	        free(out);
	    }
	
	
	    return ret;
	}
	
	int main()
	{
	    char cmd[20];
	
	    //读取数据库配置信息
	    read_cfg();
	
	    //阻塞等待用户连接
	    while (FCGI_Accept() >= 0)
	    {
	
	        // 获取URL地址 "?" 后面的内容
	        char *query = getenv("QUERY_STRING");
	
	        //解析命令
	        query_parse_key_value(query, "cmd", cmd, NULL);
	        LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "cmd = %s\n", cmd);
	
	        printf("Content-type: text/html\r\n\r\n");
	
	        if (strcmp(cmd, "count") == 0) //count 获取用户文件个数
	        {
	            get_share_files_count(); //获取共享文件个数
	        }
	        else
	        {
	            char *contentLength = getenv("CONTENT_LENGTH");
	            int len;
	
	            if( contentLength == NULL )
	            {
	                len = 0;
	            }
	            else
	            {
	                len = atoi(contentLength); //字符串转整型
	            }
	
	            if (len <= 0)
	            {
	                printf("No data from standard input.<p>\n");
	                LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "len = 0, No data from standard input\n");
	            }
	            else
	            {
	                char buf[4*1024] = {0};
	                int ret = 0;
	                ret = fread(buf, 1, len, stdin); //从标准输入(web服务器)读取内容
	                if(ret == 0)
	                {
	                    LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "fread(buf, 1, len, stdin) err\n");
	                    continue;
	                }
	
	                LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "buf = %s\n", buf);
	
	                //获取共享文件信息 127.0.0.1:80/sharefiles&cmd=normal
	                //按下载量升序 127.0.0.1:80/sharefiles?cmd=pvasc
	                //按下载量降序127.0.0.1:80/sharefiles?cmd=pvdesc
	
	                int start; //文件起点
	                int count; //文件个数
	                get_fileslist_json_info(buf, &start, &count); //通过json包获取信息
	                LOG(SHAREFILES_LOG_MODULE, SHAREFILES_LOG_PROC, "start = %d, count = %d\n", start, count);
	                 if (strcmp(cmd, "normal") == 0)
	                 {
	                    get_share_filelist(start, count); //获取共享文件列表
	                 }
	                 else if(strcmp(cmd, "pvdesc") == 0)
	                 {
	                    get_ranking_filelist(start, count);//获取共享文件排行版
	                 }
	
	
	            }
	        }
	
	    }
	
	    return 0;
	}

热门文章

暂无图片
编程学习 ·

Linux centos7 乱码设置中文字符集

1.locale 查看现在使用的字符集locale -a 查看有哪些字符集utf8的就可以显示中文yum -y install kde-l10n-Chinese 安装后选个uft8的 ,设置一下全局变量vi /etc/profileexport LANG=en_CA.utf8=号后面是字符集,这个大家随意最后让这个配置文件生效就可以了. /etc/profile 可能…
暂无图片
编程学习 ·

JavaScript-Promise的使用及详细解释

JavaScript-Promise的使用及详细解释案例使用多种方法实现以下案例第一种---setTimeout嵌套第二种---封装函数Promise详解小案例第三种---使用Promise来实现最开始的案例Promise---具体使用的案例第一版---点击按钮显示图片第二版---加载出第一张之后在加载其他,依次加载第三版…
暂无图片
编程学习 ·

使用go语言寻找最长不含有重复字符的字串,统计数量

go语言Map例题(寻找最长不含有重复字符的字串 )要求 a := abcdabc 那么得出统计说是4,实现下方代码 解题思路lastOccurred[x]不存在,或者无需操作 lastOccurred[x] >= start -> 更新start 更新lastOccurred[x],更新maxLengthfunc lengthOfNonRepeatingSubstr(s strin…
暂无图片
编程学习 ·

常用的运行脚本

常用的运行脚本1、java -Xmx1430m -cp "scenic_area_cas-1.0-SNAPSHOT.jar" scenery.extend.extendMain2、指定lib运行java -Djava.ext.dirs="./lib" -Xmx2048m -cp "subwaystationcompare-1.0-SNAPSHOT.jar" com.sogou.compareMain3、hadoop j…
暂无图片
编程学习 ·

Mathmatica多项式带余除法代码

几乎没有调用内置函数,除了求多项式最高次数时用了一下 Exponent[] (*解析多项式*) (*将f=a0+a1*x+...+an*x^n解析成{{a0,0},{a1,1},...,{an,n}}的形式*) polyCoefficients[f_] := Module[{rules1 = {c_*base_^power_ -> {c, power},base_^power_ -> {1, power},c_*x_ -…
暂无图片
编程学习 ·

Tuxera NTFS for Mac在Mac教你快速进行安全传输文件教程

Mac系统在办公性能上更加高效快捷。但是Mac电脑在U盘读取上具有局限性。它并不能读取到NTFS格式的硬盘,那么我们可以用NTFS for Mac这款神器编辑读取。具体的安装步骤 1、双击下载好的安装包(.dmg)文件,会跳出安装会话框,点击"Install Tuxera NTFS"开始安装软件…
暂无图片
编程学习 ·

unraid-APP加速方案火爆内测中!!!

unraid-APP加速方案火爆内测中!!! 声明:方案还在内测中,还没有完善的,不喜勿看。 图标已全部点亮,部分Ddocker火速下载中,插件部分等待更新,服务器继续更新中----------- 具体操作方案如下: 首先下载APP插件:https://gitlab.xcxlz.cn/shyd/community.applications/-…
暂无图片
编程学习 ·

什么是语音直播源码,语音下直播系统可以做什么?

语音直播源码是指用户能够通过语音进行聊天的软件功能。语音直播源码的形式多样化的,现在市场上也出现了很多很多语音形式的源码出现,比如,可以多人语音聊天,语音视频通话,语音直播,语音教学还有很多的语音游戏,像最近很多的和平精英,王者荣耀,狼人杀之类的,都是在游…
暂无图片
编程学习 ·

爬虫工作的代理ip选择

代理ip的使用是爬虫工作必须使用的爬取辅助工具,大数据的快速发展,很多的网站不断的维护自己的网站信息,开始设置反爬虫机制,在网站进行反爬虫限制的情况下,怎样通过反爬虫机制,提高工作效率。一:使用多线程与代理ip1、多线程方式:多线程同时开展工作采集,迅速提高工作…
暂无图片
编程学习 ·

Explicit Model Predictive Control of a Magnetic Flexible Endoscope

对胶囊的动力学进行建模,能更好的对胶囊进行控制,在已知胶囊预定义轨迹的情况下,对胶囊进行预测控制和定位。 一个磁灵活内窥镜的显式模型预测控制 Explicit Model Predictive Control of a Magnetic Flexible Endoscope [1] Paper Link Authors: Scaglioni, Bruno, et al. …
暂无图片
编程学习 ·

MFC调用winhttp实现简易的HTTP服务器程序

Windows提供的winhttp函数库用来快速实现HTTP协议的应用程序,包括客户端和服务器端。服务器开发一般流程是这样的:1.HttpInitialize 初始化WinHTTP函数库;2.HttpCreateHttpHandle 创建一个HTTP队列句柄,用来接收HTTP请求;3.HttpAddUrl 绑定要监听的URL,写为http://*:80/表…
暂无图片
编程学习 ·

蓝桥杯-试题 算法训练 审美课-java

问题描述 《审美的历程》课上有n位学生,帅老师展示了m幅画,其中有些是梵高的作品,另外的都出自五岁小朋友之手。老师请同学们分辨哪些画的作者是梵高,但是老师自己并没有答案,因为这些画看上去都像是小朋友画的……老师只想知道,有多少对同学给出的答案完全相反,这样他就…
暂无图片
编程学习 ·

直播软件开发中的音视频编码转换怎么实现

2.1、下载ffmpeg。 下载网址:[url]http://www.ffmpeg.org/download.html[/url] 2.2、解压缩tar -zxvf ffmpeg-2.0.1.tar.gz2.3、编辑profile文件: vi /etc/profile 在文件末尾加上两句话:export FFMPEG_HOME=/usr/local/ffmpeg export PATH=$FFMPEG_HOME/bin:$PATH2.4、配置…
暂无图片
编程学习 ·

quartus ii 使用modelsim altera进行仿真

第一种:先随便写一个程序,有输入,有时钟,有输出再点击processing-->start-->start test bench template writer然后就会在modlsim的文件中生成一个.vt的文件 然后打开这个文件接下来就是再initial和always里面添加信号保存,再点击首先看仿真软件是不是modelsin-altera,再…
暂无图片
编程学习 ·

Tensorflow实现卷积神经网络

Tensorflow实现卷积神经网络Tensorflow实现卷积神经网络卷积层池化层归一化层实现简单的卷积神经网络 Tensorflow实现卷积神经网络 卷积层 卷积核,步福,填充,多通道卷积,激活函数,卷积函数。 主要函数使用: 1.conv2d函数 tf.nn.conv2d(input, filter, strides, padding, …
暂无图片
编程学习 ·

创新实践记录二

创新实践记录二 一、设置菜单的制作1.1菜单切换 制作设置菜单时,为防止之前的开始菜单影响显示和操作,可以先隐藏起来关于在开始菜单和设置菜单之间的切换,可以点击设置setActive控制显示隐藏。 MainMenu的Options按钮的点击事件OptionMenu的Back按钮的点击事件 这样就完成了…
暂无图片
编程学习 ·

Spring MVC的运行原理(简答)

a)(浏览器)用户发送请求 b)前端控制器(dispatcherServlet)接收(他会委托其他模块进行真正的业务和数据处理 ) c)向handlermapping发送url查找相应的方法(handlermapping中储存的是url 和方法的键值对) d)返回处理器(“地址”)。 e)前端控制器发送处理器“地址”给处理…
暂无图片
编程学习 ·

extern随笔

extern的用法总结函数声明是可有可无的,因为函数不加修饰符默认是extern的; 全局变量在其他文件中使用时,extern关键词是必须的,如果变量在其他文件中没有extern且没有显示的初始化,则会被当成变量的定义。局部变量是不需要extern关键字描述的,而且局部变量在程序运行时才…
暂无图片
编程学习 ·

Linux防火墙安装与配置

Linux防火墙安装与配置流程一、iptables构建防火墙应用步骤如下 1、service iptables status 检查是否安装了iptables 2、systemctl stop firewalld 关闭Linux默认防火墙firewalld 3、systemctl mask firewalld 禁用firewalld服务4、y…