SDWebImage与阿里云OSS Bucket Private

2024-05-06  本文已影响0人  younger_times

实现自定义路径缓存

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内,被抓包流入公网的可能。也同时实现了图片缓存的能力。

上一篇下一篇

猜你喜欢

热点阅读