当前位置: 首页 > 知识库问答 >
问题:

如何使用NSURL会话来确定资源是否已更改?

阎声
2023-03-14

我正在使用NSURL会话从HTTP服务器请求JSON资源。服务器使用Cache-Control来限制资源在客户端上缓存的时间。

这效果很好,但我也想在内存中缓存反序列化的JSON对象,因为它经常被访问,同时继续利用NSURLSESION中内置的HTTP缓存机制。

我想我可以保存几个HTTP响应头:Content-MD5EtagLast Modified以及反序列化的JSON对象(我之所以使用这三个字段,是因为我注意到并非所有HTTP服务器都返回 .否则就足够了)。下次我收到JSON对象的响应时,如果这3个字段相同,那么我可以重用以前反序列化的JSON对象

这是确定反序列化JSON仍然有效的可靠方法吗?如果不是,如何确定反序列化对象是否是最新的?

共有2个答案

饶骁
2023-03-14

这可以通过简单的HTTP标准响应来完成。

假设之前的响应如下所示:

{ status code: 200, headers {
    "Accept-Ranges" = bytes;
    Connection = "Keep-Alive";
    "Content-Length" = 47616;
    Date = "Thu, 23 Jul 2015 10:47:56 GMT";
    "Keep-Alive" = "timeout=5, max=100";
    "Last-Modified" = "Tue, 07 Jul 2015 11:28:46 GMT";
    Server = Apache;
} }

现在使用下面的命令告诉服务器如果没有修改,就不要发送日期。

NSURLSession是一个可配置的容器,您可能需要使用http选项“IF Modified Since”

下载资源前使用以下配置类型,

    NSURLSessionConfiguration *backgroundConfigurationObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"myBackgroundSessionIdentifier"];
    [backgroundConfigurationObject setHTTPAdditionalHeaders:
     @{@"If-Modified-Since": @"Tue, 07 Jul 2015 11:28:46 GMT"}];

例如,如果资源没有从上述设定日期更改,则将调用以下委托

    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
    {

    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) downloadTask.response;
        if([httpResponse statusCode] == 304)
                //resource is not modified since last download date
    }

查看downloadTask。response状态代码为304,则不修改资源,也不下载资源。

注意:在某些< code>NSUserDefaults中保存上次成功完全下载的日期,以便在if-modified-since中设置它

江佐
2023-03-14

我创建了一个 HTTPEntity指纹结构,用于存储一些实体标头:内容 MD5Etag上次修改时间

import Foundation

struct HTTPEntityFingerprint {
    let contentMD5 : String?
    let etag : String?
    let lastModified : String?
}

extension HTTPEntityFingerprint {
    init?(response : NSURLResponse) {
        if let httpResponse = response as? NSHTTPURLResponse {
            let h = httpResponse.allHeaderFields
            contentMD5 = h["Content-MD5"] as? String
            etag = h["Etag"] as? String
            lastModified = h["Last-Modified"] as? String

            if contentMD5 == nil && etag == nil && lastModified == nil {
                return nil
            }
        } else {
            return nil
        }
    }

    static func match(first : HTTPEntityFingerprint?, second : HTTPEntityFingerprint?) -> Bool {
        if let a = first, b = second {
            if let md5A = a.contentMD5, md5B = b.contentMD5 {
                return md5A == md5B
            }
            if let etagA = a.etag, etagB = b.etag {
                return etagA == etagB
            }
            if let lastA = a.lastModified, lastB = b.lastModified {
                return lastA == lastB
            }
        }

        return false
    }
}

当我从 NSURL 会话中获取 NSHTTPURL 响应时,我会从中创建一个 HTTPEntity指纹,并将其与以前使用 HTTPEntit指纹打印.match 存储的指纹进行比较。如果指纹匹配,则HTTP资源没有更改,因此我不需要再次反序列化JSON响应;但是,如果指纹不匹配,则我反序列化JSON响应并保存新指纹。

此机制仅在您的服务器返回3个实体标头中的至少一个时才有效:Content-MD5EtagLast-Modified

通过NSURLCache提供的缓存是透明的,这意味着当您请求以前缓存的资源时,NSURLSession将调用完成处理程序/委托,就像发生了200个响应一样。

如果缓存的响应已过期,则NSURL会话将向源服务器发送一个新请求,但将使用缓存(尽管过期)结果中的Last-Modified和Etag实体标头包含If-Modified-FromIf-No-Match标头;此行为是内置的,除了启用缓存之外,您无需执行任何操作。如果源服务器返回304(未修改),则NSURL会话将其转换为应用程序的200响应(使其看起来像您获取了资源的新副本,即使它仍然从缓存中提供)。

 类似资料:
  • 问题内容: 如何调用会话对象,检查会话是一个新会话还是已在使用中? 我读到,如果客户端尚未使用会话ID进行响应,则返回true。但是这是什么意思 ?请解释 问题答案: 我读到,如果客户端尚未使用会话ID进行响应,则isNew()返回true。但是这是什么意思 ? 考虑服务器当前正在处理请求。关于会话处理,有两种方案。 在新的会话方案中,服务器正在为用户/客户端创建一个新的会话。(客户端可能未在请求

  • 问题内容: 我如何断言页面的CSS已在Watin 2.1中成功加载并应用了其样式? 问题答案: 在进行了一些研究并写下我的答案之后,我偶然发现了该链接,该链接解释了您需要了解的有关CSS的所有信息,何时加载CSS以及如何检查CSS。 实际上,所提供的链接对它的解释很好,以至于我在其中添加了一些引用以供将来参考。 如果您好奇,我的答案将是#2和#4的变体。 何时真正加载样式表? … 顺便说一句,让我

  • 我设置了一个会话,根据每个用户的角色控制菜单...例如,我有这个 现在,如果我想不登录就进入该页面呢?我试图在不登录的情况下进入该页面,但基本上遇到了,因为我没有在角色中存储任何会话。我在用户登录时设置每个会话。不登录时,我想查看不需要任何角色的菜单。。。例如,我重定向到该页面,其中一个链接可以被其他人查看。 当我没有登录时,我如何仍然查看目录菜单?

  • 问题内容: 我正在编写一些Javascript来调整大图像的大小,以适合用户的浏览器窗口。(不幸的是,我没有控制源图像的大小。) 因此,HTML中将包含以下内容: 我是否可以确定 标签中的图像是否已下载? 我需要这样做,因为如果在浏览器加载图像之前执行该命令,就会遇到问题。 并返回占位符的大小(替代文本)。就我而言,这大约是134 x 20。 现在,我只是在检查照片的高度是否小于150,并假设是a

  • 本文向大家介绍如何检查PHP会话是否已经开始?,包括了如何检查PHP会话是否已经开始?的使用技巧和注意事项,需要的朋友参考一下 在PHP中,我们利用一个内置函数session_start()来启动会话。但是,PHP脚本中面临的问题是,如果我们多次执行它会引发错误。因此,在这里我们将学习如何在不调用session_start()函数两次的情况下检查会话是否启动。 有两种方法可以解决此问题。 对于低于

  • 不管错误情况如何,使用资源尝试是否总是关闭资源?我的意思是考虑以下代码: 会一直关闭吗?我读过Oracle文档,其中说: 无论try语句是正常完成还是突然完成,它都将关闭 因此无论程序正常运行还是抛出异常,它都将起作用。但是,类似或崩溃的情况怎么办?我知道这些条件对块不起作用。那么,使用资源尝试失败的条件是否存在? 这只是我请求的好奇心,谁能说明这一点吗?