繁体   English   中英

是否可以防止将带有响应标头`Cache-Control:Private`的文件缓存在NSURLCache中?

[英]Would a file with a response header `Cache-Control:Private` be prevented from being cached in a NSURLCache?

是否可以防止将带有响应标头Cache-Control:Private的文件缓存在NSURLCache 共享缓存(如setSharedCacheNSURLCache.sharedCache() )还是自定义缓存?

为了进行扩展,我具有UIWebView ,离线时需要访问它。 WebView的源具有与其关联的多个外部CSS和JS文件。 我可以缓存大多数站点(CSS等都放在适当的位置),但是似乎没有缓存提供站点重要信息的特定JavaScript文件。 我注意到不会缓存的文件与其余文件之间的区别是,它的Cache-Control设置为私有(其他是公共的)。 但是,据我了解,将缓存控件设置为私有是为了防止在代理服务器上缓存。 它会影响iOS上的缓存吗?

设置缓存

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    let URLCache: NSURLCache = NSURLCache(memoryCapacity: 10 * 1024 * 1024,
                                            diskCapacity: 50 * 1024 * 1024,
                                                diskPath: nil)

    NSURLCache.setSharedURLCache(URLCache)

    println("Disk cache usage: \(NSURLCache.sharedURLCache().currentDiskUsage)")

    // http://stackoverflow.com/questions/21957378/how-to-cache-using-nsurlsession-and-nsurlcache-not-working
    sleep(1)

    return true
}

使用缓存

func getWebPage(onCompletion: (NSString, NSURL) -> Void) {

    let url = getApplicationSelectorURL()

    let request = NSURLRequest(URL: url, cachePolicy: .ReturnCacheDataElseLoad, timeoutInterval: 10.0)

    let queue = NSOperationQueue()

    NSURLConnection.sendAsynchronousRequest(request, queue: queue, completionHandler: { response, data, error in
        println("Web page task completed")

        var cachedResponse: NSCachedURLResponse

        if (error != nil) {
            println("NSURLConnection error: \(error.localizedDescription)")
            if let cachedResponse = NSURLCache.sharedURLCache().cachedResponseForRequest(request) {
                if let htmlString = NSString(data: cachedResponse.data, encoding: NSUTF8StringEncoding) {
                    onCompletion(htmlString, url)
                } else {
                    println("htmlString nil")
                }
            } else {
                println("cacheResponse nil")
            }
        } else {
            cachedResponse = NSCachedURLResponse(response: response, data: data, userInfo: nil, storagePolicy: .Allowed)
            NSURLCache.sharedURLCache().storeCachedResponse(cachedResponse, forRequest: request)
            if let htmlString = NSString(data: data, encoding: NSUTF8StringEncoding) {
                onCompletion(htmlString, url)
            } else {
                println("htmlString nil")
            }
        }
    })
}

填充UIWebView

APICommunicator.sharedInstance.getWebPage({ htmlString, url in

    dispatch_async(dispatch_get_main_queue(),{
        self.webView.loadHTMLString(htmlString, baseURL: url)
    })

})

我最终创建了一个类似于NSURLConnectionDelegate方法willCacheResponse的方法,并替换了Cache-Control:private标头。

willCacheResponse方法

func willCacheResponse(cachedResponse: NSCachedURLResponse) -> NSCachedURLResponse?
{        
    let response = cachedResponse.response

    let HTTPresponse: NSHTTPURLResponse = response as NSHTTPURLResponse

    let headers: NSDictionary = HTTPresponse.allHeaderFields

    var modifiedHeaders: NSMutableDictionary = headers.mutableCopy() as NSMutableDictionary

    modifiedHeaders["Cache-Control"] = "max-age=604800"

    let modifiedResponse: NSHTTPURLResponse = NSHTTPURLResponse(
            URL: HTTPresponse.URL!,
            statusCode: HTTPresponse.statusCode,
            HTTPVersion: "HTTP/1.1",
            headerFields: modifiedHeaders)!

    let modifiedCachedResponse = NSCachedURLResponse(
            response: modifiedResponse,
            data: cachedResponse.data,
            userInfo: cachedResponse.userInfo,
            storagePolicy: cachedResponse.storagePolicy)

    return modifiedCachedResponse
}

调用方法

if let cachedResponse = self.willCacheResponse(
        NSCachedURLResponse(response: response,
                                data: data,
                            userInfo: nil,
                       storagePolicy: .Allowed)) {

    NSURLCache.sharedURLCache().storeCachedResponse(cachedResponse, forRequest: request)
}

现在,它在脱机时可以正确显示。 真是一段旅程。

是的, NSURLCache不会缓存具有专用缓存控制策略的NSURLCache RFC#2616

私人:指示全部或部分响应消息是针对单个用户的,并且不得由共享缓存缓存。 这允许源服务器声明响应的指定部分仅面向一个用户,而不是针对其他用户的请求的有效响应。 私有(非共享)缓存可以缓存响应。

好吧, NSURLCache使用了sharedCache ,您甚至可以在发布的代码中进行设置。 我猜它可以解释几乎所有内容。

解决方案是更改服务器行为,或重写NSURLCache类的某些方法。 (例如,您可以重写客户端头文件,但这确实是一个很糟糕的技巧。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM