SharePoint 2016 Rest API‘僵尸ItemID缓存Bug’技术问题咨询
我在帮客户迁移SharePoint 2013 JavaScript应用到2016环境时,碰到过完全一致的问题,这个REST API的缓存坑确实挺头疼的,咱们来梳理下细节和解决办法:
问题复现场景
你当前的代码逻辑是连续两个AJAX调用:
- 上传文件到文档库,返回
spFile对象 - 通过
spFile.d.ListItemAllFields.__deferred.uri请求对应的列表项
- 正常情况:目标路径无同名文件时,能正确获取新创建的列表项ID
- 异常情况:如果该路径曾有同名文件且已被删除,SP2016会生成新ID的列表项(这部分符合预期),但第二个AJAX调用返回的却是已删除的旧项ID,而非新创建的ID
这个问题的触发条件很明确:
- 仅在SharePoint 2016中出现,SP2013完全正常
- 两个AJAX调用必须处于同一浏览器上下文
- 大多在「上传文件+同步更新元数据」的场景下暴露出来
问题根源
这是SP2016的一个已知类Bug,核心原因是REST API的缓存机制设计过于严格:当删除同名文件后,服务器端或浏览器会缓存旧文件关联的列表项URI响应,后续请求直接命中缓存,没有去拉取新创建的列表项数据。
可行的解决方案
针对这个问题,我测试过几个有效的修复方案,你可以根据自己的代码场景选择:
方案1:强制禁用请求缓存
在第二个获取列表项的AJAX请求中,添加cache: false参数直接绕过浏览器缓存;或者在URL后拼接随机参数,确保每次请求的URL唯一,避免命中缓存:
// 方法A:使用jQuery的cache参数 jQuery.ajax({ url: file.d.ListItemAllFields.__deferred.uri, type: "GET", headers: { "accept": "application/json;odata=verbose" }, cache: false, // 禁用浏览器缓存 success: function (result) { var id = result.d.ID; // 你的后续业务逻辑 } }); // 方法B:拼接随机参数 var uniqueRequestUrl = file.d.ListItemAllFields.__deferred.uri + "?nocache=" + new Date().getTime(); jQuery.ajax({ url: uniqueRequestUrl, type: "GET", headers: { "accept": "application/json;odata=verbose" }, success: function (result) { var id = result.d.ID; // 你的后续业务逻辑 } });
方案2:直接用文件ID构造列表项请求URL
上传文件返回的spFile对象中已经包含了对应的列表项ID(file.d.ID),你可以直接构造列表项的请求URL,完全避开__deferred.uri这个可能触发缓存的路径:
success: function (file) { // 从返回的spFile中拿到列表项ID var targetItemId = file.d.ID; // 直接构造列表项请求URL var listItemRequestUrl = "/sites/mysite/_api/web/lists/getByTitle('myLibrary')/items(" + targetItemId + ")"; jQuery.ajax({ url: listItemRequestUrl, type: "GET", headers: { "accept": "application/json;odata=verbose" }, success: function (result) { var id = result.d.ID; // 你的后续业务逻辑 } }); }
方案3:添加X-RequestDigest强制刷新
虽然X-RequestDigest通常用于POST/PUT/DELETE请求,但在GET请求中添加这个头,可以强制SP服务器返回最新数据,避免命中服务器端缓存:
jQuery.ajax({ url: file.d.ListItemAllFields.__deferred.uri, type: "GET", headers: { "accept": "application/json;odata=verbose", "X-RequestDigest": params.digest // 复用上传时的请求digest }, success: function (result) { var id = result.d.ID; // 你的后续业务逻辑 } });
验证小技巧
测试的时候可以打开浏览器开发者工具的「网络」面板,查看第二个请求的响应头:
- 如果看到
Cache-Control: no-cache或者响应状态是200(而非304),说明缓存已经被成功绕过 - 也可以用隐私模式测试,排除浏览器本地缓存的干扰
内容的提问来源于stack exchange,提问作者Stefan Bretschneider
相关产品推荐
相关产品推荐

