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

有一些开发者可能会遇到一种情况,当服务器端的图片改变而url没改变的时候,客户端的图片不会更新成最新的图片。这是为什么呢,往下看 -->

方法一:

1、

我们来简单探讨一下SDWebImage的实现原理: SDWebImageManager内部利用SDWebImageDownloader来下载,它的缓存策略有两种,一种是用NSURL缓存,一种是自己定义了SDImageCache(内部使用NSCache)进行缓存。 如果设置了SDWebImageRefreshCached标示位,那么SDWebImageDownloader则利用NSURL进行缓存,而且使用的policy为NSURLRequestUseProtocolCachePolicy。 那么如果设置了SDWebImageRefreshCached标识位,图片是否更新则要取决于你服务器的cache-control设置了,如果没有cache-control的话,客户端则然享受不了自动更新的功能。 所以说仅仅设置SDWebImageRefreshCached往往是不能解决问题的。。。。 那么如何查看服务器是否支持cache-control呢? 其实简单,只需要要终端输入

curl [url] --head

这就可以了。

2、

基于这一现象,我们来进行分析。 客户端第一次请求图片时,Charles抓包得知response header里有一个名为Last-Modified、数据是时间戳的键值对。

客户端第二次及以后请求图片时,通过Charles抓包发现,服务器返回304 not modified状态,说明服务器在接收客户端请求后通过某种判断逻辑得出结论:“客户端已缓存的图片与服务器图片都是最新的”,那么服务器如何判断的呢?

通过查阅HTTP协议相关的资料得知,与服务器返回的Last-Modified相对应的request header里可以加一个名为If-Modified-Since的key,value即是服务器回传的服务端图片最后被修改的时间,第一次图片请求时If-Modified-Since的值为空,第二次及以后的客户端请求会把服务器回传的Last-Modified值作为If-Modified-Since的值传给服务器,这样服务器每次接收到图片请求时就将If-Modified-Since与Last-Modified进行比较,如果客户端图片已陈旧那么返回状态码200、Last-Modified、图片内容,客户端存储Last-Modified和图片;如果客户端图片是最新的那么返回304 Not Modified、不会返回Last-Modified、图片内容。

关于服务器的比较逻辑,需要强调一下。

经查资料得知,Apache比较时是看If-Modified-Since之后有没有更新图片,Nginx比较时是看If-Modified-Since与Last-Modified是否相等,所以对于Apache服务器环境客户端每次都要严格的存储服务器回传的Last-Modified以便下次请求时作为If-Modified-Since的值传给服务器,对于Nginx服务器环境客户端不必存储服务器回传的Last-Modified,每次请求时只需将图片自身的fileModificationDate作为If-Modified-Since的值传服务器即可。在实际开发中,如果遇到明明传了If-Modified-Since、服务器图片也变更了、但是客户端却请求不到最新的图片的情况时,那么就需要查看一下服务器对这两个时间戳的比较逻辑。

那么,现在我们可以回到SDWebImage上来了。通过查看SDWebImageDownloader的源码得知,它开放了一个headersFilter的block,意在让开发者可以对所有图片请求追加一些额外的header,这正合我意。那么我们就可以在诸如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 > 0 ? lastModifiedStr : @"";
[mutableHeaders setValue:lastModifiedStr forKey:@"If-Modified-Since"];

return mutableHeaders;
复制代码

};

然后,加载图片的地方以前怎么写还是怎么写,但别忘了Option是SDWebImageRefreshCached

NSURL *imgURL = [NSURL URLWithString:@"handy-img-storage.b0.upaiyun.com/3.jpg"];

[[self imageView] sd_setImageWithURL:imgURL placeholderImage:nil options:SDWebImageRefreshCached];

方法二:

在SDWebImageManager.m大约167行的

if (cachedImage && options & SDWebImageRefreshCached) {

     // force progressive off if image already cached but forced refreshing
    downloaderOptions &= ~SDWebImageDownloaderProgressiveDownload;
     // ignore image read from NSURLCache if image if cached but force refreshing
     downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse;
复制代码

}

中间加上:

// remove SDWebImageDownloaderUseNSURLCache flag downloaderOptions &= ~SDWebImageDownloaderUseNSURLCache;

变成:

if (cachedImage && options & SDWebImageRefreshCached) {

            // force progressive off if image already cached but forced refreshing
            downloaderOptions &= ~SDWebImageDownloaderProgressiveDownload;
            // remove SDWebImageDownloaderUseNSURLCache flag
            downloaderOptions &= ~SDWebImageDownloaderUseNSURLCache;
            // ignore image read from NSURLCache if image if cached but force refreshing
            downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse;
        }复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值