HBHttpRequestCache.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. //
  2. // HBHttpRequestCache.m
  3. // wq
  4. //
  5. // Created by weqia on 13-8-15.
  6. // Copyright (c) 2013年 Weqia. All rights reserved.
  7. //
  8. #import "HBHttpRequestCache.h"
  9. #import "HBHttpCacheData.h"
  10. #import <CommonCrypto/CommonDigest.h>
  11. #import <mach/mach.h>
  12. #import <mach/mach_host.h>
  13. @implementation HBHttpRequestCache
  14. -(id)init
  15. {
  16. self=[super init];
  17. if(self){
  18. /**创建数据库,如果不存在*/
  19. _dbHelper=[[LKDBHelper alloc]init];
  20. [_dbHelper createTableWithModelClass:[HBHttpCacheData class]];
  21. /**默认文件路径**/
  22. NSArray * paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  23. NSMutableString * path=[NSMutableString stringWithString:[paths objectAtIndex:0]];
  24. [path appendFormat:@"/HBHttpCache"];
  25. _cacheFilePath=path;
  26. /****创建缓存目录****/
  27. NSFileManager * manager=[NSFileManager defaultManager];
  28. if(![manager fileExistsAtPath:_cacheFilePath])
  29. [manager createDirectoryAtPath:_cacheFilePath withIntermediateDirectories:YES attributes:nil error:NULL];
  30. /***设置内存缓存****/
  31. _memoryCache=[[NSCache alloc]init];
  32. [_memoryCache setTotalCostLimit:7*1024*1024]; //默认最大缓存空间为7M
  33. /***穿件线程队列**/
  34. _queue=dispatch_queue_create("com.HBHhttp.imageCache", NULL);
  35. /***默认过期时间为三天***/
  36. _staleTime=24*60*60*3;
  37. _timeLimit=NO; //默认期限开关为关
  38. }
  39. return self;
  40. }
  41. #pragma -mark 私有方法
  42. -(void)clearCache
  43. {
  44. dispatch_async(_queue, ^{
  45. /**获取所有图片路径**/
  46. NSArray* array=[_dbHelper search:[HBHttpCacheData class] where:[NSString stringWithFormat:@"cacheType=%d",HBHttpCacheDataTypeImage] orderBy:nil offset:0 count:MAXFLOAT];
  47. NSFileManager * manager=[NSFileManager defaultManager];
  48. for(HBHttpCacheData * cache in array){
  49. [manager removeItemAtPath:cache.cacheData error:nil]; //删除所有图片路径
  50. }
  51. [LKDBHelper clearTableData:[HBHttpCacheData class]]; // 清空数据库
  52. [self clearMemoryCache]; // 清除内存缓存
  53. });
  54. }
  55. /******检测缓存数据是否过期*****/
  56. -(BOOL)timeOutCheck:(HBHttpCacheData*)data
  57. {
  58. NSDate * date=[NSDate date];
  59. long long now=(long long)date.timeIntervalSince1970;
  60. if((now-data.timestamp.longLongValue)>_staleTime){
  61. [self timeOutCheck:data];
  62. return YES;
  63. }else{
  64. return NO;
  65. }
  66. }
  67. /********检测到数据过期后的操作*********/
  68. -(void)timeOutAction:(HBHttpCacheData*)data
  69. {
  70. if(data.cacheType==HBHttpCacheDataTypeText){
  71. [_dbHelper deleteToDB:data];
  72. }else if(data.cacheType==HBHttpCacheDataTypeImage){
  73. NSFileManager * manager=[NSFileManager defaultManager];
  74. [manager removeItemAtPath:data.cacheData error:nil];
  75. [_dbHelper deleteToDB:data];
  76. }
  77. }
  78. #pragma -mark 接口方法
  79. +(HBHttpRequestCache*)shareCache
  80. {
  81. static HBHttpRequestCache * server=nil;
  82. static dispatch_once_t onceToken;
  83. dispatch_once(&onceToken, ^{
  84. server=[[HBHttpRequestCache alloc]init];
  85. });
  86. return server;
  87. }
  88. +(void)clearCache
  89. {
  90. [[self shareCache] clearCache];
  91. }
  92. - (void)clearOneCache:(NSString *)url{
  93. [_memoryCache removeObjectForKey:url];
  94. }
  95. -(void)setTimeLimit:(long long)time
  96. {
  97. _staleTime=time;
  98. }
  99. /*********根据传入的url生成文件名称**********/
  100. -(NSString *)getFileName:(NSString*)key
  101. {
  102. const char *str = [key UTF8String];
  103. unsigned char r[CC_MD5_DIGEST_LENGTH];
  104. CC_MD5(str, (CC_LONG)strlen(str), r);
  105. return [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
  106. r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]];
  107. }
  108. -(BOOL)storeTextToDB:(NSString*)text withUrl:(NSString*)url
  109. {
  110. /*******生成缓存对象,并设置内容*********/
  111. HBHttpCacheData * cache=[[HBHttpCacheData alloc]init];
  112. cache.cacheData=text;
  113. cache.cacheUrl=url;
  114. cache.cacheType=HBHttpCacheDataTypeText;
  115. /*******判断当前缓存中是否已经存在该内容*********/
  116. int rowCount=[_dbHelper rowCount:[HBHttpCacheData class] where:@{@"cacheUrl":url}];
  117. if(rowCount==0)
  118. return [_dbHelper insertToDB:cache]; // 如果缓存中不存在则直接插入
  119. else {
  120. if([_dbHelper deleteToDB:cache])
  121. return [_dbHelper insertToDB:cache];
  122. else
  123. return NO;
  124. } //如果已经存在,则更新内容
  125. }
  126. -(NSString*) getTextFromDB:(NSString*)url
  127. {
  128. HBHttpCacheData * cache=[_dbHelper searchSingle:[HBHttpCacheData class] where:@{@"cacheUrl":url} orderBy:nil];
  129. /****检测是否过期***/
  130. if(_timeLimit){
  131. if([self timeOutCheck:cache])
  132. return nil;
  133. }
  134. if(cache&&cache.cacheType==HBHttpCacheDataTypeText)
  135. return cache.cacheData;
  136. return nil;
  137. }
  138. -(BOOL)storeBitmapToMemory:(UIImage*)image withKey:(NSString*)key
  139. {
  140. id object=[_memoryCache objectForKey:key];
  141. if(object==nil){
  142. if(image){
  143. [_memoryCache setObject:image forKey:key];
  144. return YES;
  145. }else
  146. return NO;
  147. }else
  148. return NO;
  149. }
  150. -(void)storeBitmapToDisk:(UIImage*)image withKey:(NSString*)key complete:(void(^)(BOOL))complete
  151. {
  152. dispatch_async(_queue, ^{
  153. BOOL success=NO;
  154. /*****生成文件路径*****/
  155. NSMutableString * fileName=[NSMutableString stringWithString:_cacheFilePath];
  156. [fileName appendFormat:@"/%@",[self getFileName:key]];
  157. /*******生成缓存对象,并设置内容*********/
  158. HBHttpCacheData * cache=[[HBHttpCacheData alloc]init];
  159. cache.cacheData=fileName;
  160. cache.cacheType=HBHttpCacheDataTypeImage;
  161. cache.cacheUrl=key;
  162. /*******判断当前缓存中是否已经存在该内容*********/
  163. int rowCount=[_dbHelper rowCount:[HBHttpCacheData class] where:@{@"cacheUrl":key}];
  164. if(rowCount==0){ // 如果缓存中不存在则直接插入
  165. if([_dbHelper insertToDB:cache]){
  166. NSFileManager * manager=[NSFileManager defaultManager];
  167. //在该路径下创建文件,如果创建失败,数据库回滚
  168. if(![manager createFileAtPath:fileName contents:UIImageJPEGRepresentation(image, 0.5) attributes:nil]){
  169. [_dbHelper deleteToDB:cache];
  170. }else{
  171. success=YES;
  172. }
  173. }
  174. }else{ //如果已经存在,则更新该路径下的文件
  175. NSFileManager * manager=[NSFileManager defaultManager];
  176. [manager removeItemAtPath:cache.cacheData error:nil];
  177. if(![manager createFileAtPath:fileName contents:UIImageJPEGRepresentation(image, 0.5) attributes:nil]){
  178. [_dbHelper deleteToDB:cache]; // 如果更新文件失败,则删除该条数据库记录
  179. }else{
  180. success=YES;
  181. }
  182. }
  183. dispatch_async(dispatch_get_main_queue(), ^{
  184. complete(success);
  185. });
  186. });
  187. }
  188. -(void)storeBitmap:(UIImage*)image withKey:(NSString*)key complete:(void(^)(BOOL))complete
  189. {
  190. /***先将图片缓存到硬盘中***/
  191. [self storeBitmapToDisk:image withKey:key complete:^(BOOL success) {
  192. if(success){ // 如果成功缓存到硬盘,则继续缓存到内存中
  193. [self storeBitmapToMemory:image withKey:key];
  194. }
  195. if(complete){
  196. complete(success);
  197. }
  198. }];
  199. }
  200. -(UIImage*)getBitmapFromMemory:(NSString*)key
  201. {
  202. return [_memoryCache objectForKey:key];
  203. }
  204. -(void)getBitmapFromDisk:(NSString*)key complete:(void(^)(UIImage *))complete
  205. {
  206. dispatch_async(_queue, ^{
  207. /***从数据库中获取缓存路径 **/
  208. HBHttpCacheData * cache=[_dbHelper searchSingle:[HBHttpCacheData class] where:@{@"cacheUrl":key} orderBy:nil];
  209. /****检测是否过期***/
  210. if(_timeLimit){
  211. if([self timeOutCheck:cache]){
  212. complete(nil);
  213. }
  214. }
  215. if(cache&&cache.cacheType==HBHttpCacheDataTypeImage){ //如果缓存存在并且缓存类型为图片类型
  216. /**判断该路径是否存在文件*/
  217. NSFileManager * manager=[NSFileManager defaultManager];
  218. if(![manager fileExistsAtPath:cache.cacheData]){
  219. /**如果该路径下不存在文件或者已经被删除,则删除掉该条数据库记录**/
  220. [_dbHelper deleteToDB:cache];
  221. complete(nil); // 执行回调,并返回nil
  222. }
  223. /**文件存在,则生成图片**/
  224. UIImage *image=[UIImage imageWithContentsOfFile:cache.cacheData];
  225. if(image==nil){
  226. /**如果文件格式不正确,则删除该条数据库记录,并且删除该文件**/
  227. [_dbHelper deleteToDB:cache];
  228. [manager removeItemAtPath:cache.cacheData error:nil];
  229. complete(nil);
  230. }
  231. dispatch_async(dispatch_get_main_queue(), ^{
  232. complete(image);
  233. });
  234. }
  235. else{
  236. dispatch_async(dispatch_get_main_queue(), ^{
  237. complete(nil);
  238. });
  239. }
  240. });
  241. }
  242. -(UIImage*)getBitmapFromDisk:(NSString *)key
  243. {
  244. HBHttpCacheData * cache=[_dbHelper searchSingle:[HBHttpCacheData class] where:@{@"cacheUrl":key} orderBy:nil];
  245. /****检测是否过期***/
  246. if(_timeLimit){
  247. if([self timeOutCheck:cache]){
  248. return nil;
  249. }
  250. }
  251. if(cache&&cache.cacheType==HBHttpCacheDataTypeImage){ //如果缓存存在并且缓存类型为图片类型
  252. /**判断该路径是否存在文件*/
  253. NSFileManager * manager=[NSFileManager defaultManager];
  254. if(![manager fileExistsAtPath:cache.cacheData]){
  255. /**如果该路径下不存在文件或者已经被删除,则删除掉该条数据库记录**/
  256. [_dbHelper deleteToDB:cache];
  257. return nil; // 执行回调,并返回nil
  258. }
  259. /**文件存在,则生成图片**/
  260. UIImage *image=[UIImage imageWithContentsOfFile:cache.cacheData];
  261. if(image==nil){
  262. /**如果文件格式不正确,则删除该条数据库记录,并且删除该文件**/
  263. [_dbHelper deleteToDB:cache];
  264. [manager removeItemAtPath:cache.cacheData error:nil];
  265. return nil;
  266. }
  267. return image;
  268. }
  269. return nil;
  270. }
  271. -(void)getBitmap:(NSString*)key complete:(void(^)(UIImage *))complete
  272. {
  273. /**先从内存缓存中获取**/
  274. UIImage * image=[self getBitmapFromMemory:key];
  275. if(image)
  276. complete(image);
  277. else{
  278. /**如果内存缓存中不存在,则到硬盘中获取**/
  279. [self getBitmapFromDisk:key complete:^(UIImage * image){
  280. if(image){
  281. [self storeBitmapToMemory:image withKey:key];
  282. }
  283. if(complete){
  284. complete(image);
  285. }
  286. }];
  287. }
  288. }
  289. -(void) clearMemoryCache
  290. {
  291. [_memoryCache removeAllObjects];
  292. }
  293. -(void) clearDiskCache
  294. {
  295. NSFileManager * manager=[NSFileManager defaultManager];
  296. if([manager fileExistsAtPath:_cacheFilePath]){
  297. [manager removeItemAtPath:_cacheFilePath error:NULL];
  298. [manager createDirectoryAtPath:_cacheFilePath withIntermediateDirectories:YES attributes:nil error:NULL];
  299. }
  300. }
  301. -(void)setDirectoryAtPath:(NSString*) path
  302. {
  303. _cacheFilePath=path;
  304. NSFileManager * manager=[NSFileManager defaultManager];
  305. if(![manager fileExistsAtPath:_cacheFilePath])
  306. [manager createDirectoryAtPath:_cacheFilePath withIntermediateDirectories:YES attributes:nil error:NULL];
  307. }
  308. @end