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