实现自定义路径缓存
let image = SDImageCache(namespace:items[indexPath.row].id.description.MD5(), diskCacheDirectory: DocumentPath! + "/MD_img/preview/") //将ID MD5后,作为文件夹名,存放于 Document/MD_img/preview下
let manager = SDWebImageManager(cache: image, loader: loader)
//获取缓存,如果存在读取缓存
if let localImg = image.imageFromDiskCache(forKey: url.absoluteString){
cell.img.image = localImg
}else{
//不存在缓存,下载
manager.loadImage(with: url, progress: nil) {img, _, _, _, _, _ in
cell.img.image = img
}
}
SDWebImage与OSS的安全策略
为了避免额外的流量费用,避免图片等资源流入外网;OSS的策略中,Private
只有授权才能访问。大多数为了图方便选择Public
。
如果将选择Private
,就需要以下的配置:
定义了一个Config
根据项目实际情况,进行自操作。
class OSSUploader: NSObject {
struct Config {
static var oss_domain = ""
static var accessKeyId = ""
static var accessKeySecret = ""
static var bucketName = ""
static var endpoint = ""
static let expirationInterval:TimeInterval = 3600 //图片过期时间:私有访问【Bucket ACL】 时间:【秒】
}
}
扩展两个分类
它的作用在于,帮你完成访问图片时,拼接后面权限的参数
public extension String{
///在URL中包含签名【读写权限:私有】
var OSSSafeUrl:String{
let url = Foundation.URL(string: self)
if let objectKey = url?.relativePath.jq_substring(from: 1){
let response = OBSUploader.shared.ossClient.presignConstrainURL(withBucketName: OBSUploader.Config.bucketName, withObjectKey: objectKey, withExpirationInterval: OBSUploader.Config.expirationInterval)
if response.isSuccessful(){
guard let urlsafe = response.result as? String else { return self }
return urlsafe
}
}
return self
}
}
public extension URL{
///在URL中包含签名 【读写权限:私有】
var OSS_SafeUrl:URL{
let objectKey = self.relativePath.jq_substring(from: 1)
let response = OBSUploader.shared.ossClient.presignConstrainURL(withBucketName: OBSUploader.Config.bucketName, withObjectKey: objectKey, withExpirationInterval: OBSUploader.Config.expirationInterval)
if response.isSuccessful(){
guard let urlsafe = response.result as? String else { return self }
return URL(string:urlsafe) ?? self
}
return self
}
}
引发的问题
以上就已经实现了对Private
的资源读取,但会发现一个问题,每一次请求都是以新链接请求,那么SDWebImage
都会认为是新链接,会重新进行一次下载,就造成了缓存的图片URL,相同资源会多次缓存。刷新List时,明显出现闪动。这并不是我们想要的缓存效果。
原因:SDWebImage
缓存的原理在将URL进行MD5为图片名称,OSS的Private后,参数都不一样,MD5后都会不同。
可以通过以下方法解决:
对manager
实现cacheKeyFilter
,对URL后面部分参数截取,将前面的链接作为需要MD5的KEY。
manager.cacheKeyFilter = SDWebImageCacheKeyFilter(block: { url in
let img = url.absoluteString.components(separatedBy: "?").first
return img
})
将下载图片的改为OSS_SafeUrl
:
manager.loadImage(with: url.OSS_SafeUrl, progress: nil) {img, _, _, _, _, _ in
cell.img.image = img
}
通过模拟器打印路径发现,即使采用了Private
策略,图片依然是只有一张,保护了APP内,被抓包流入公网的可能。也同时实现了图片缓存的能力。
网友评论