SDWebImage 处理URL不变图片资源改变的情况2

本文介绍如何使用SDWebImage实现图片缓存更新,确保客户端能及时获取到最新的图片内容,通过合理利用Last-Modified及ETag进行缓存比对。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.sina.com.cn/s/blog_75a855980102wfvp.html

SDWebImage支持URL不变时更新图片内容

关于SDWebImage支持URL不变时更新图片内容的问题,博客 http://blog.handy.wang/blog/2016/01/29/sdwebimagehuan-cun-zhi-tu-pian-urlbu-bian/ 有了很好的解释,可供参考。

结论就是当图片url不变,内容更新了后,想要客户端更新图片缓存需要做两步:
1.加载图片的地方设置Option是SDWebImageRefreshCached;
2.在诸如AppDelegate didFinishLaunching的地方追加如下代码:

SDWebImageDownloader *imgDownloader SDWebImageManager.sharedManager.imageDownloader;
imgDownloader.headersFilter  = ^NSDictionary *(NSURL *url, NSDictionary *headers) {

    NSFileManager *fm [[NSFileManager alloc] init];
    NSString *imgKey [SDWebImageManager.sharedManager cacheKeyForURL:url];
    NSString *imgPath [SDWebImageManager.sharedManager.imageCache defaultCachePathForKey:imgKey];
    NSDictionary *fileAttr [fm attributesOfItemAtPath:imgPath error:nil];

    NSMutableDictionary *mutableHeaders [headers mutableCopy];

    NSDate *lastModifiedDate nil;

    if (fileAttr.count 0) {
        if (fileAttr.count 0) {
            lastModifiedDate (NSDate *)fileAttr[NSFileModificationDate];
        }

    }
    NSDateFormatter *formatter [[NSDateFormatter alloc] init];
    formatter.timeZone [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
    formatter.locale [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
    formatter.dateFormat @"EEE, dd MMM yyyy HH:mm:ss z";

    NSString *lastModifiedStr [formatter stringFromDate:lastModifiedDate];
    lastModifiedStr lastModifiedStr.length lastModifiedStr @"";
    [mutableHeaders setValue:lastModifiedStr forKey:@"If-Modified-Since"];

    return mutableHeaders;
};

这段代码是以本地url对应的缓存图片更新时间转换成“If-Modified-Since”的value值传给服务器,服务器拿到该值后与服务端的Last-Modified值做对比,而本地转换的总是和服务端不相等,导致同一张图片实际上是不断从服务器下载更新了,验证方法:(1)在沙盒中查看同一张图片的更新时间,是一直变化的 (2)在[self.imageView sd_setImageWithURL:url placeholderImage:defaultImage options:SDWebImageRefreshCached completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {} 的block中打断点,下载图片时查看SDImageCacheType 值,会发现一张图片会断两次,第一从缓存读取,第二次为cacheType 值为 SDImageCacheTypeNone,重新下载了一次更新本地图片,也就是会一直从服务器下载图片更新本地,显然不合逻辑。
     更好的做法还是严格的将Last-Modified 或ETag值缓存起来,url为key,下载图片时将Last-Modified或ETag回传给服务器,两个一起传更好。通过查看SDWebImage源码发现,每次下载图片收到服务器响应时,会发送SDWebImageDownloadReceiveResponseNotification通知,将SDWebImageDownloaderOperation作为参数传出,而SDWebImageDownloaderOperation有response和request,那么就好办了,我们取出response中的Last-Modified和Etag作为value值,同时取出request的RUR.absoluteString作为key,缓存起来,请求图片时将url对应的Last-Modified、ETag取出在SDWebImageDownloader的headersFilter设置一下传给服务器,有服务器来进行对比。有关服务器的对比逻辑请查看以上参考链接。
//************************************* ***********************************************************************
-(void)sdWebImageConfig{
   
    [[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(sdWebImageDownloadReceiveResponseNotification:)name:SDWebImageDownloadReceiveResponseNotification object:nil];
   
    SDWebImageDownloader *imgDownloader =SDWebImageManager.sharedManager.imageDownloader;
    imgDownloader.headersFilter  = ^NSDictionary *(NSURL *url, NSDictionary*headers) {
      
        NSMutableDictionary *mutableHeaders = [headers mutableCopy];
       
        NSString * lastModifiedStr = [[SBAppCoreInfo getCacheDB]getStrValue:EMGlobal_LastModified_Cache  dataKey:url.absoluteString];
        NSString * etagStr = [[SBAppCoreInfo getCacheDB]getStrValue:EMGlobal_ETag_Cache  dataKey:url.absoluteString];
       
        [mutableHeaders setValue:lastModifiedStr forKey:@"If-Modified-Since"];
        [mutableHeaders setValue:etagStr forKey:@"If-None-Match"];

        return mutableHeaders;
    };
}

-(void)sdWebImageDownloadReceiveResponseNotification:(NSNotification *)note{
    SDWebImageDownloaderOperation  downloaderOperation = (SDWebImageDownloaderOperation *)note.object;
    NSString * urlKey = downloaderOperation.request.URL.absoluteString;
     NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)downloaderOperation.response;
    //缓存Last-ModifiedETag
    [[SBAppCoreInfo getCacheDB] setStrValue:EMGlobal_LastModified_CachedataKey:urlKey dataValue:httpResponse.allHeaderFields[@"Last-Modified"]];
    [[SBAppCoreInfo getCacheDB] setStrValue:EMGlobal_ETag_Cache dataKey:urlKeydataValue:httpResponse.allHeaderFields[@"ETag"]];
}

//************************************* ***********************************************************************
其中 EMGlobal_LastModified_Cache、EMGlobal_ETag_Cache是定义的宏,

[[SBAppCoreInfo getCacheDB] setStrValue:(NSString *)string dataKey:urlKeydataValue:httpResponse.allHeaderFields[@"ETag"]]

[[SBAppCoreInfo getCacheDB] getStrValue:(NSString *)string dataKey:url.absoluteString];
方法是公司封装的缓存类,我们也可以用plist缓存这两个值。这样沙盒中的图片不会一直更新,只有同一个url图片发生改变,即服务端图片的 Last-Modified、ETag发生改变,才会更新客户端该图片的缓存。
如何查看图片url得  Last-Modified、 ETag值?在终端 输入 curl 图片url --head 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值