ASIHTTPRequest - 来自缓存的数据始终为空

Posted

技术标签:

【中文标题】ASIHTTPRequest - 来自缓存的数据始终为空【英文标题】:ASIHTTPRequest - data from cache always empty 【发布时间】:2011-06-25 13:50:26 【问题描述】:

我正在我的 iPhone/iPad 应用程序中下载图像 - 因为它们大部分时间都保持不变,所以我想将它们缓存在磁盘上:

ASIDownloadCache *cache = [ASIDownloadCache sharedCache];
[asiRequest setDownloadCache:cache];
[asiRequest setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
[asiRequest setCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
[asiRequest setSecondsToCache:60*60*24*30]; // Cache for 30 days
[asiRequest setDelegate:self]; // A delegate must be specified
[asiRequest setDidFinishSelector:@selector(requestFinished:)];
[asiRequest startAsynchronous];

在我的requestFinished-method中,可以识别出缓存是成功的,但是我的request-object里面的数据是空的;我错过了什么?

- (void) requestFinished:(ASIHTTPRequest *)request 
   if ([request didUseCachedResponse]) 
       NSLog(@"cache, size: %i", [[request responseData] length]); // is always zero
       [self buildImageWithData:[request responseData]];
   
   [...];

非常感谢!

编辑 1: 我的完整代码不起作用:第一次,我得到“未缓存”语句,从那时起,“缓存,大小:0”......我有不知道为什么:(

- (void)viewDidLoad 
    [super viewDidLoad];

    for (int i = 0; i < 10; i++) 
        asiRequest = [[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.myimageserver.com/myimage.jpg"]];

        ASIDownloadCache *cache = [ASIDownloadCache sharedCache];
        [asiRequest setDownloadCache:cache];
        [asiRequest setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
        [asiRequest setCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
        [asiRequest setSecondsToCache:60*60*24*30]; // Cache for 30 days
        [asiRequest setDelegate:self]; // A delegate must be specified
        [asiRequest setDidFinishSelector:@selector(requestFinished:)];
        [asiRequest startAsynchronous];
    


- (void) request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders 
    self.imageDataLoadedFromURL = [NSMutableData data];


- (void) request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data 
    [imageDataLoadedFromURL appendData:data];


- (void) requestFinished:(ASIHTTPRequest *)request 
    if ([request didUseCachedResponse]) 
        NSLog(@"cache, size: %i", [[request responseData] length]); // is always zero
     else 
        NSLog(@"not cached");
    

编辑 2: 似乎缓存已经包含 0 字节图像;所以这不是从缓存中读取而是写入它的问题......

编辑3:你可以从http://tinyurl.com/68wuwj2下载小测试项目

【问题讨论】:

【参考方案1】:

您能否设置断点,清除缓存(例如,删除您的应用程序),然后单步执行这段代码(ASIDownloadCache.m,第 184 行,方法 storeResponseForRequest):

if ([request responseData]) 
    [[request responseData] writeToFile:dataPath atomically:NO];
 else if ([request downloadDestinationPath] && ![[request downloadDestinationPath] isEqualToString:dataPath]) 
    NSError *error = nil;
    [[[[NSFileManager alloc] init] autorelease] copyItemAtPath:[request downloadDestinationPath] toPath:dataPath error:&error];

检查走哪条路径,检查request.responseData的大小。

** 编辑 **

你的问题是你对 didReceiveData 的使用:

- (void) request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data 
    [imageDataLoadedFromURL appendData:data];

引用 asi http 请求文档:

如果您需要将响应处理为 它进来了(例如,你想 使用流解析器来解析 仍在进行中的响应 下载),让你的代表 实现请求:didReceiveData:(见 ASIHTTPRequestDelegate.h)。 请注意 当你这样做时,ASIHTTPRequest 将 不填充 responseData 或写入 响应 downloadDestinationPath - 您必须自己存储响应 如果需要。

最后一句话似乎也适用于缓存数据。

这可能是 asihttprequest 中的一个错误,实际上在这种情况下它不应该将数据写入缓存,或者应该确保它正在写入有效数据 - 目前看起来它写入了一个无效的缓存条目。您是否需要在数据到达时对其进行处理?如果不只是删除 'didReceiveBytes' 并仅使用 requestFinished 中 request.responseData 中提供的数据。

【讨论】:

@"接收数据的大小:%d 个字节", [[request responseData] length] => 给出 0 个字节;它采用第一个路径,因此它将 0 写入文件... 如果您完全禁用缓存(即停止读取或写入缓存,因此它将始终从服务器获取),您的应用程序是否工作?看来您的问题可能不是缓存问题,而是服务器返回的数据有问题。 感谢您的测试应用程序,这让它变得更加容易 - 我已经更新了我的答案!【参考方案2】:

您的代码对我来说似乎是正确的。

我唯一能想到的是,您的缓存中可能有一些“损坏”的数据,例如存储零长度数据的情况。您可以尝试只删除一次缓存或只使用一次ASIDoNotReadFromCacheCachePolicy 策略(以便“清除”缓存)。

如果这没有帮助,我会在您的requestFinished: 中设置一个断点,然后从那里准确检查据称从缓存中检索数据时 ASIHTTP 中发生了什么。这比听起来容易。

【讨论】:

这就是我的观点;在 requestFinished:-method 中,数据已经是空的。不幸的是,ASIDoNotReadFromCacheCachePolicy 不起作用……我真的不知道这里出了什么问题……【参考方案3】:

注释掉这个方法:

(void) request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data

   [imageDataLoadedFromURL appendData:data];

【讨论】:

【参考方案4】:

试试这个,告诉我你得到了什么:

- (void) requestFinished:(ASIHTTPRequest *)request 
    NSLog(@"Size of received data: %d bytes",[[request responseData] length]); //THIS LINE

if ([request didUseCachedResponse]) 
    NSLog(@"cached");        
 else 
        NSLog(@"not cached");
    

然后尝试将此方法更改为:

- (void) request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders 
    [self.imageDataLoadedFromURL setLength:0];

并确保您使用 self.imageDataLoadedFromURL 作为 NSMutableData

【讨论】:

%lu 是不可能的(编译器错误);我只能使用“%u”,结果也是 0。 didReceiveResponseHeaders 的更改没有任何后果; imageDataLoadedFromURL 是 NSMutableData... 没有改变任何东西;另请参阅我更新的原始帖子;似乎写入缓存不起作用... Size of received data: %d bytes 总是显示 0 ?您还没有使用更新的代码或您的真实图像是 0 字节 我的真实图像是 0,因为我在缓存中找到了它(请参阅我的原始帖子的编辑) 我的意思是你的服务器图像。Size of received data: %d bytes 总是显示 0 吗?【参考方案5】:

我尝试运行您的应用。亚历山大的建议是对的。

注释掉这个方法:

(void) request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data

在注释掉这个方法时,调用的 requestDone 方法将具有整个请求内容,因此具有大小。

【讨论】:

以上是关于ASIHTTPRequest - 来自缓存的数据始终为空的主要内容,如果未能解决你的问题,请参考以下文章

ASIHTTPRequest 下载缓存问题 - 无法在缓存中保存/加载日期

目标 C - 使用 ASIHTTPRequest 来自 GET 的 HTTP/0.9 响应

ASIHTTPRequest + WCF POST XML

ASIHTTPRequest框架的简单使用

ASIHttpRequest或者SDWebImage给UIImageView加载图片的逻辑是什么样子的

ASIHttpRequest - 如何将参数的 NSDictionary 转换为 url 编码的查询参数字符串?