我正在使用NSURL会话从HTTP服务器请求JSON资源。服务器使用Cache-Control来限制资源在客户端上缓存的时间。
这效果很好,但我也想在内存中缓存反序列化的JSON对象,因为它经常被访问,同时继续利用NSURLSESION中内置的HTTP缓存机制。
我想我可以保存几个HTTP响应头:Content-MD5
、EtagLast Modified
以及反序列化的JSON对象(我之所以使用这三个字段,是因为我注意到并非所有HTTP服务器都返回
.否则就足够了)。下次我收到JSON对象的响应时,如果这3个字段相同,那么我可以重用以前反序列化的JSON对象。
这是确定反序列化JSON仍然有效的可靠方法吗?如果不是,如何确定反序列化对象是否是最新的?
这可以通过简单的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中设置它
我创建了一个 HTTPEntity指纹结构,用于存储一些实体标头:内容 MD5
、Etag
和上次修改时间
。
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-MD5
、Etag
或Last-Modified
。
通过NSURLCache提供的缓存是透明的,这意味着当您请求以前缓存的资源时,NSURLSession将调用完成处理程序/委托,就像发生了200个响应一样。
如果缓存的响应已过期,则NSURL会话将向源服务器发送一个新请求,但将使用缓存(尽管过期)结果中的Last-Modified和Etag
实体标头包含If-Modified-From
和If-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语句是正常完成还是突然完成,它都将关闭 因此无论程序正常运行还是抛出异常,它都将起作用。但是,类似或崩溃的情况怎么办?我知道这些条件对块不起作用。那么,使用资源尝试失败的条件是否存在? 这只是我请求的好奇心,谁能说明这一点吗?