3.7 分享/ 删除文件/ 更新下载数
1、/api/dealfile?cmd=share 分享文件
具体流程是:
◼ 先判断此文件是否已经分享,判断集合有没有这个文件,如果有,说明别人已经分享此文件,中断操作(redis操作)。
◼ 如果集合没有此元素,可能因为redis中没有记录,再从mysql中查询,如果mysql也没有,说明真没有(mysql操作)
◼ 如果mysql有记录,而redis没有记录,说明redis没有保存此文件,redis保存此文件信息后,再中断操作(redis操作)
◼ 如果此文件没有被分享,mysql保存一份持久化操作(mysql操作)
◼ redis集合中增加一个元素(redis操作)
◼ redis对应的hash也需要变化 (redis操作)
//文件标示,md5+文件名 sprintf(fileid, "%s%s", md5.c_str(), filename.c_str()); if (cache_conn) { ret2 = cache_conn->ZsetExit(FILE_PUBLIC_ZSET, fileid); } else { ret2 = 0; } LogInfo("fileid: {}, ZsetExit: {}", fileid, ret2); //===1、先判断此文件是否已经分享,判断集合有没有这个文件,如果有,说明别人已经分享此文件,中断操作(redis操作) if (ret2 == 1) //存在 { LogWarn("别人已经分享此文件"); share_state = ShareHad; goto END; } else if (ret2 == 0) //不存在 { //===2、如果集合没有此元素,可能因为redis中没有记录,再从mysql中查询,如果mysql也没有,说明真没有(mysql操作) //===3、如果mysql有记录,而redis没有记录,说明redis没有保存此文件,redis保存此文件信息后,再中断操作(redis操作) //查看此文件别人是否已经分享了 sprintf(sql_cmd, "select * from share_file_list where md5 = '%s' and file_name " "= '%s'", md5.c_str(), filename.c_str()); //返回值:1有记录 ret2 = CheckwhetherHaveRecord( db_conn, sql_cmd); //执行sql语句, 最后一个参数为NULL //,如果有则说明没有及时保持到redis,这里需要保存到redis if (ret2 == 1) //说明有结果,别人已经分享此文件 { // redis保存此文件信息 cache_conn->ZsetAdd(FILE_PUBLIC_ZSET, 0, fileid); cache_conn->Hset(FILE_NAME_HASH, fileid, filename); LogWarn("别人已经分享此文件"); share_state = ShareHad; goto END; } } else //出错 { ret = -1; goto END; } //===4、如果此文件没有被分享,mysql保存一份持久化操作(mysql操作) // sql语句, 更新共享标志字段 sprintf(sql_cmd, "update user_file_list set shared_status = 1 where user = '%s' and " "md5 = '%s' and file_name = '%s'", user.c_str(), md5.c_str(), filename.c_str()); if (!db_conn->ExecuteUpdate(sql_cmd, false)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } time_t now; ; char create_time[TIME_STRING_LEN]; //获取当前时间 now = time(NULL); strftime(create_time, TIME_STRING_LEN - 1, "%Y-%m-%d %H:%M:%S", localtime(&now)); //分享文件的信息,额外保存在share_file_list保存列表 /* -- user 文件所属用户 -- md5 文件md5 -- create_time 文件共享时间 -- file_name 文件名字 -- pv 文件下载量,默认值为1,下载一次加1 */ sprintf(sql_cmd, "insert into share_file_list (user, md5, create_time, file_name, " "pv) values ('%s', '%s', '%s', '%s', %d)", user.c_str(), md5.c_str(), create_time, filename.c_str(), 0); if (!db_conn->ExecuteCreate(sql_cmd)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } // 共享文件数量+1 ret = CacheIncrCount(cache_conn, FILE_PUBLIC_COUNT); if (ret < 0) { LogError("CacheIncrCount failed"); ret = -1; goto END; } //===5、redis集合中增加一个元素(redis操作) cache_conn->ZsetAdd(FILE_PUBLIC_ZSET, 0, fileid); // 如果失败是需要撤销mysql数据库的操作的 //===6、redis对应的hash也需要变化 (redis操作) // fileid ------> filename LogInfo("Hset FILE_NAME_HASH {}-{}", fileid, filename); ret = cache_conn->Hset(FILE_NAME_HASH, fileid, filename); if (ret < 0) { LogWarn("Hset FILE_NAME_HASH failed"); } share_state = ShareOk; END: return (int)share_state;
2、/api/dealfile?cmd=del 删除文件
1)先判断此文件是否已经分享
◼ 判断集合有没有这个文件,如果有,说明别人已经分享此文件(redis 操作)
◼ 如果集合没有此元素,可能因为 redis 中没有记录,再从 mysql 中查询,如果 mysql 也没有,说明真没有(mysql 操作)
//文件标识,文件md5+文件名 sprintf(fileid, "%s%s", md5.c_str(), filename.c_str()); //===1、先判断此文件是否已经分享,判断集合有没有这个文件,如果有,说明别人已经分享此文件 ret2 = cache_conn->ZsetExit(FILE_PUBLIC_ZSET, fileid); LogInfo("ret2: {}", ret2); if (ret2 == 1) //存在 { is_shared = 1; //共享标志 redis_has_record = 1; // redis有记录 } else if (ret2 == 0) //不存在 { //===2、如果集合没有此元素,可能因为redis中没有记录,再从mysql中查询,如果mysql也没有,说明真没有(mysql操作) is_shared = 0; // sql语句 //查看该文件是否已经分享了 sprintf(sql_cmd, "select shared_status from user_file_list where user = '%s' " "and md5 = '%s' and file_name = '%s'", user.c_str(), md5.c_str(), filename.c_str()); LogInfo("执行: {}", sql_cmd); int shared_status = 0; ret2 = GetResultOneStatus(db_conn, sql_cmd, shared_status); //执行sql语句 if (ret2 == 0) { LogInfo("GetResultOneCount share = {}", shared_status); is_shared = shar ed_status; // 要从mysql里面获取赋值 } } else //出错 { ret = -1; goto END; }
2)若此文件被分享,删除分享列表(share_file_list)的数据
◼ 如果 mysql 有记录,而 redis 没有记录,那么分享文件处理只需要处理 mysql (mysql 操作)
◼ 如果 redis 有记录,mysql 和 redis 都需要处理,删除相关记录
//说明此文件被分享,删除分享列表(share_file_list)的数据 if (is_shared == 1) { //===3、如果mysql有记录,删除相关分享记录 (mysql操作) // 删除在共享列表的数据, 如果自己分享了这个文件,那同时从分享列表删除掉 sprintf(sql_cmd, "delete from share_file_list where user = '%s' and md5 = '%s' " "and file_name = '%s'", user.c_str(), md5.c_str(), filename.c_str()); LogInfo("执行: {}", sql_cmd); if (!db_conn->ExecuteDrop(sql_cmd)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } //共享文件的数量-1 //查询共享文件数量 if (CacheDecrCount(cache_conn, FILE_PUBLIC_COUNT) < 0) { LogError("CacheDecrCount 操作失败"); ret = -1; goto END; } //===4、如果redis有记录,redis需要处理,删除相关记录 if (1 == redis_has_record) { //有序集合删除指定成员 cache_conn->ZsetZrem(FILE_PUBLIC_ZSET, fileid); //从hash移除相应记录 cache_conn->Hdel(FILE_NAME_HASH, fileid); } }
3)删除用户文件列表的数据,并使用户文件数量-1
//用户文件数量-1 if (CacheDecrCount(cache_conn, FILE_USER_COUNT + user) < 0) { LogError("CacheDecrCount 操作失败"); ret = -1; goto END; } //删除用户文件列表数据 sprintf(sql_cmd, "delete from user_file_list where user = '%s' and md5 = '%s' and " "file_name = '%s'", user.c_str(), md5.c_str(), filename.c_str()); LogInfo("执行: {}", sql_cmd); if (!db_conn->ExecuteDrop(sql_cmd)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; }
4)文件信息表(file_info)的文件引用计数count,减去1。如果count=0,说明没有用户引用此文件,需要在storage删除此文件
//查看该文件文件引用计数 sprintf(sql_cmd, "select count from file_info where md5 = '%s'", md5.c_str()); LogInfo("执行: {}", sql_cmd); count = 0; ret2 = GetResultOneCount(db_conn, sql_cmd, count); //执行sql语句 LogInfo("ret2: {}, count: {}", ret2, count); if (ret2 != 0) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } if (count > 0) { count -= 1; sprintf(sql_cmd, "update file_info set count=%d where md5 = '%s'", count, md5.c_str()); LogInfo("执行: {}", sql_cmd); if (!db_conn->ExecuteUpdate(sql_cmd)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } } if (count == 0) //说明没有用户引用此文件,需要在storage删除此文件 { //查询文件的id sprintf(sql_cmd, "select file_id from file_info where md5 = '%s'", md5.c_str()); string fileid; CResultSet *result_set = db_conn->ExecuteQuery(sql_cmd); if (result_set->Next()) { fileid = result_set->GetString("file_id"); } //删除文件信息表中该文件的信息 sprintf(sql_cmd, "delete from file_info where md5 = '%s'", md5.c_str()); if (!db_conn->ExecuteDrop(sql_cmd)) { LogWarn("{} 操作失败", sql_cmd); } //从storage服务器删除此文件,参数为为文件id ret2 = RemoveFileFromFastDfs(fileid.c_str()); if (ret2 != 0) { LogInfo("RemoveFileFromFastDfs err: {}", ret2); ret = -1; goto END; } } ret = 0;
3、/api/dealfile?cmd=pv 更新文件下载计数
用来更新指定文件的下载量,每次成功下载一个文件成功后,调用该接口更新对应文件的 pv 值。
// sql语句 //查看该文件的pv字段 sprintf(sql_cmd, "select pv from user_file_list where user = '%s' and md5 = '%s' " "and file_name = '%s'", user.c_str(), md5.c_str(), filename.c_str()); LogInfo("执行: {}", sql_cmd); CResultSet *result_set = db_conn->ExecuteQuery(sql_cmd); if (result_set && result_set->Next()) { pv = result_set->GetInt("pv"); } else { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } //更新该文件pv字段,+1 sprintf(sql_cmd, "update user_file_list set pv = %d where user = '%s' and md5 = " "'%s' and file_name = '%s'", pv + 1, user.c_str(), md5.c_str(), filename.c_str()); LogInfo("执行: {}", sql_cmd); if (!db_conn->ExecuteUpdate(sql_cmd)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; }
3.8 取消分享/ 转存/ 更新下载计数
1、/dealsharefile?cmd=cancel 取消分享
//文件标示,md5+文件名 sprintf(fileid, "%s%s", md5.c_str(), filename.c_str()); // 1、共享标志设置为0 sprintf(sql_cmd, "update user_file_list set shared_status = 0 where user = '%s' and " "md5 = '%s' and file_name = '%s'", user_name.c_str(), md5.c_str(), filename.c_str()); LogInfo("执行: {}", sql_cmd); if (!db_conn->ExecuteUpdate(sql_cmd, false)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } // 2、共享文件数量-1 ret2 = CacheDecrCount(cache_conn, FILE_PUBLIC_COUNT); if (ret2 < 0) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } //3、删除在共享列表的数据 sprintf(sql_cmd, "delete from share_file_list where user = '%s' and md5 = '%s' and " "file_name = '%s'", user_name.c_str(), md5.c_str(), filename.c_str()); LogInfo("执行: {}, ret = {}", sql_cmd, ret); if (!db_conn->ExecuteDrop(sql_cmd)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } //4、redis记录操作 //4.1 有序集合删除指定成员 ret = cache_conn->ZsetZrem(FILE_PUBLIC_ZSET, fileid); if (ret != 0) { LogInfo("执行: ZsetZrem 操作失败"); goto END; } //4.2 从hash移除相应记录 LogInfo("Hdel FILE_NAME_HASH {}", fileid); ret = cache_conn->Hdel(FILE_NAME_HASH, fileid); if (ret < 0) { LogInfo("执行: hdel 操作失败: ret = {}", ret); goto END; }
2、/api/dealsharefile?cmd=e save 转存文件
◼ 先查询是个人文件列表是否已经存在该文件。
◼ 增加 file_info表的 count 计数,表示多一个人保存了该文件。
◼ 个人的 user_file_list 增加一条文件记录
◼ 更新个人的 user_file_count
当我们转存该文件后,即使分享者删除自己的文件,不会影响到我们自己转存的文件。
//查看此用户,文件名和md5是否存在,如果存在说明此文件存在 sprintf(sql_cmd, "select * from user_file_list where user = '%s' and md5 = '%s' and " "file_name = '%s'", user_name.c_str(), md5.c_str(), filename.c_str()); ret2 = CheckwhetherHaveRecord(db_conn, sql_cmd); // 有记录返回1,错误返回-1,无记录返回0 if (ret2 == 1) { //如果有结果,说明此用户已有此文件 LogError("user_name: {}, filename: {}, md5: {} 已存在", user_name, filename, md5); ret = -2; //返回-2错误码 goto END; } if (ret2 < 0) { LogError("{} 操作失败", sql_cmd); ret = -1; //返回-1错误码 goto END; } //文件信息表,查找该文件的计数器 sprintf(sql_cmd, "select count from file_info where md5 = '%s'", md5.c_str()); count = 0; ret2 = GetResultOneCount(db_conn, sql_cmd, count); //执行sql语句 if (ret2 != 0) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } // 1、修改file_info中的count字段,+1 (count 文件引用计数) sprintf(sql_cmd, "update file_info set count = %d where md5 = '%s'", count + 1, md5.c_str()); if (!db_conn->ExecuteUpdate(sql_cmd)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } // 2、user_file_list插入一条数据 gettimeofday(&tv, NULL); ptm = localtime( &tv.tv_sec); //把从1970-1-1零点零分到当前时间系统所偏移的秒数时间转换为本地时间 // strftime() // 函数根据区域设置格式化本地时间/日期,函数的功能将时间格式化,或者说格式化一个时间字符串 strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", ptm); // sql语句 /* -- =============================================== 用户文件列表 -- user 文件所属用户 -- md5 文件md5 -- create_time 文件创建时间 -- file_name 文件名字 -- shared_status 共享状态, 0为没有共享, 1为共享 -- pv 文件下载量,默认值为0,下载一次加1 */ sprintf(sql_cmd, "insert into user_file_list(user, md5, create_time, file_name, " "shared_status, pv) values ('%s', '%s', '%s', '%s', %d, %d)", user_name.c_str(), md5.c_str(), time_str, filename.c_str(), 0, 0); if (!db_conn->ExecuteCreate(sql_cmd)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } // 3、查询用户文件数量,更新该字段数量+1 if (CacheIncrCount(cache_conn, FILE_USER_COUNT + user_name) < 0) { LogError("CacheIncrCount 操作失败"); ret = -1; goto END; }
3、/api/dealsharefile?cmd=pv 更新共享文件下载计数
更新 share_file_list 的 pv 值
更新 redis 里的 FILE_PUBLIC_ZSET,用作排行榜
//文件标示,md5+文件名 sprintf(fileid, "%s%s", md5.c_str(), filename.c_str()); //===1、mysql的下载量+1(mysql操作) // sql语句 //查看该共享文件的pv字段 sprintf( sql_cmd, "select pv from share_file_list where md5 = '%s' and file_name = '%s'", md5.c_str(), filename.c_str()); LogInfo("执行: {}", sql_cmd); CResultSet *result_set = db_conn->ExecuteQuery(sql_cmd); if (result_set && result_set->Next()) { pv = result_set->GetInt("pv"); } else { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } //更新该文件pv字段,+1 sprintf(sql_cmd, "update share_file_list set pv = %d where md5 = '%s' and file_name " "= '%s'", pv + 1, md5.c_str(), filename.c_str()); LogInfo("执行: {}", sql_cmd); if (!db_conn->ExecuteUpdate(sql_cmd, false)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } //===2、判断元素是否在集合中(redis操作) ret2 = cache_conn->ZsetExit(FILE_PUBLIC_ZSET, fileid); if (ret2 == 1) //===3、如果存在,有序集合score+1 { ret = cache_conn->ZsetIncr( FILE_PUBLIC_ZSET, fileid); // zrange FILE_PUBLIC_ZSET 0 -1 withscores 查看 if (ret != 0) { LogError("ZsetIncr 操作失败"); } } else if (ret2 == 0) //===4、如果不存在,从mysql导入数据 { //===5、redis集合中增加一个元素(redis操作) cache_conn->ZsetAdd(FILE_PUBLIC_ZSET, pv + 1, fileid); //===6、redis对应的hash也需要变化 (redis操作) // fileid ------> filename cache_conn->Hset(FILE_NAME_HASH, fileid, filename); } else //出错 { ret = -1; goto END; }
3.9 图床分享图片
1、/api/sharepic?cmd=share 请求图片分享
前端:
1)访问链接:http://xxx.xxx.xxx.xxx/602fdf30db2aacf517badf456512123,该
访问链接由 web 服务器提供。
2)访问链接的 web 向 后台服务器请求图片下载地址
请求接口 http://xxx.xxx.xxx.xxx/api/sharepic?cmd=browse
请求格式 { “urlmd5”: “602fdf30db2aacf517badf4565121234” // 来自请求链接 } 返回格式 { “code”: 0, “url”: “http://xxx.xxx.xxx.xxx/602fdf30db2aacf517badf4565121234”, // 图片的下载地址 “user”: “qingfu”, // 分享者用户名 “pv”: 1, // 浏览次数 “time”: “2021-12-12 11:23:0” // 分享时间 }
web 页面获取到 url 后下载图片显示,并显示分享者用户名和分享时间。
// 1. 生成urlmd5 string urlmd5; urlmd5 = RandomString(32); // 这里我们先简单的,直接使用随机数代替 MD5的使用 LogInfo("urlmd5: {}", urlmd5); // 2. 插入share_picture_list,即添加图片分享记录 time_t now; //获取当前时间 now = time(NULL); strftime(create_time, TIME_STRING_LEN - 1, "%Y-%m-%d %H:%M:%S", localtime(&now)); sprintf(sql_cmd, "insert into share_picture_list (user, filemd5, file_name, urlmd5, " "`key`, pv, create_time) values ('%s', '%s', '%s', '%s', '%s', %d, " "'%s')", user, filemd5, file_name, urlmd5.c_str(), key, 0, create_time); LogInfo("执行: {}", sql_cmd); if (!db_conn->ExecuteCreate(sql_cmd)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } //3、文件信息表,获取该共享图片的数量 sprintf(sql_cmd, "select count from file_info where md5 = '%s'", filemd5); count = 0; ret = GetResultOneCount(db_conn, sql_cmd, count); //执行sql语句 if (ret != 0) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } // 4、修改file_info中的count字段,即该共享图片的数量+1 (count 文件引用计数) sprintf(sql_cmd, "update file_info set count = %d where md5 = '%s'", count + 1, filemd5); if (!db_conn->ExecuteUpdate(sql_cmd)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; } // 5、 增加分享图片计数 SHARE_PIC_COUNTdarren if (CacheIncrCount(cache_conn, SHARE_PIC_COUNT + string(user)) < 0) { LogError(" CacheIncrCount 操作失败"); }
2、/api/sharepic?cmd=browse 请求浏览图片
请求接口 http://xxx.xxx.xxx.xxx/api/sharepic?cmd=browse,主要用来返回具体的图片下载地址。
// 1. 先从分享图片列表查询到文件信息 sprintf(sql_cmd, "select user, filemd5, file_name, pv, create_time from " "share_picture_list where urlmd5 = '%s'", urlmd5); LogDebug("执行: {}", sql_cmd); result_set = db_conn->ExecuteQuery(sql_cmd); if (result_set && result_set->Next()) { user = result_set->GetString("user"); filemd5 = result_set->GetString("filemd5"); file_name = result_set->GetString("file_name"); pv = result_set->GetInt("pv"); create_time = result_set->GetString("create_time"); delete result_set; } else { if (result_set) delete result_set; ret = -1; goto END; } // 2. 通过文件的MD5查找对应的url地址 sprintf(sql_cmd, "select url from file_info where md5 ='%s'", filemd5.c_str()); LogInfo("执行: {}", sql_cmd); result_set = db_conn->ExecuteQuery(sql_cmd); if (result_set && result_set->Next()) { picture_url = result_set->GetString("url"); delete result_set; } else { if (result_set) delete result_set; ret = -1; goto END; } // 3. 更新浏览次数, 可以考虑保存到redis,减少数据库查询的压力 pv += 1; //浏览计数增加 sprintf(sql_cmd, "update share_picture_list set pv = %d where urlmd5 = '%s'", pv, urlmd5); LogDebug("执行: {}", sql_cmd); if (!db_conn->ExecuteUpdate(sql_cmd)) { LogError("{} 操作失败", sql_cmd); ret = -1; goto END; }
3、/api/sharepic?cmd=normal 我的图片分享
4、/api/sharepic?cmd=cance 取消图片分享
需要注意的是,如果文件引用次数(分享次数)为0,说明没人引用了,需要从文件信息表和fastdfs的storage删除。
// 获取文件md5 LogInfo("urlmd5: {}", urlmd5); // 1. 查看是否有分享记录,先从分享图片列表查询到文件信息 sprintf(sql_cmd, "select filemd5 from share_picture_list where urlmd5 = '%s'", urlmd5); LogDebug("执行: {}", sql_cmd); result_set = db_conn->ExecuteQuery(sql_cmd); if (result_set && result_set->Next()) { filemd5 = result_set->GetString("filemd5"); delete result_set; } else { if (result_set) delete result_set; ret = -1; goto END; } //2、查询文件信息表(file_info)的文件引用计数count sprintf(sql_cmd, "select count, file_id from file_info where md5 = '%s' for update", filemd5.c_str()); // LogInfo("执行: {}", sql_cmd); result_set = db_conn->ExecuteQuery(sql_cmd); if (result_set && result_set->Next()) { fileid = result_set->GetString("file_id"); count = result_set->GetInt("count"); delete result_set; } else { if (result_set) delete result_set; LogError("{} 操作失败", sql_cmd); ret = -1; // db_conn->Rollback(); goto END; } // 3. 更新文件信息表的文件引用数count - 1 if (count > 0) { count -= 1; sprintf(sql_cmd, "update file_info set count=%d where md5 = '%s'", count, filemd5.c_str()); LogInfo("执行: {}", sql_cmd); if (!db_conn->ExecuteUpdate(sql_cmd)) { LogError("{} 操作失败", sql_cmd); ret = -1; // db_conn->Rollback(); goto END; } } //4、删除在共享图片列表的数据 sprintf( sql_cmd, "delete from share_picture_list where user = '%s' and urlmd5 = '%s'", user, urlmd5); LogInfo("执行: {}", sql_cmd); if (!db_conn->ExecutePassQuery(sql_cmd)) { LogError("{} 操作失败", sql_cmd); ret = -1; // db_conn->Rollback(); goto END; } // 5、若count=0,说明没有用户引用此文件,需要在文件信息表和storage删除此文件 if (count == 0) { //删除文件信息表中该文件的信息 sprintf(sql_cmd, "delete from file_info where md5 = '%s'", filemd5.c_str()); LogInfo("执行: {}", sql_cmd); if (!db_conn->ExecuteDrop(sql_cmd)) { LogWarn("{} 操作失败", sql_cmd); ret = -1; goto END; } LogWarn("RemoveFileFromFastDfs"); //从storage服务器删除此文件,参数为为文件id ret2 = RemoveFileFromFastDfs(fileid.c_str()); if (ret2 != 0) { LogError("RemoveFileFromFastDfs err: {}", ret2); ret = -1; goto END; } } // 6、共享图片数量-1 if (CacheDecrCount(cache_conn, SHARE_PIC_COUNT + string(user)) < 0) { LogError("CacheDecrCount failed"); // 即使失败 也可以下次从mysql加载计数 }