讲师中心 微信公众号
AI工具推荐 视频效率加速

service worker如何拦截和缓存XML上传请求

阿宇小哥_3543

阿宇小哥_3543

发布时间:2026-03-04 09:59:03

|

527人浏览过

|

来源于php中文网

原创

Service Worker 能拦截 XMLHttpRequest 的 POST 请求但无法缓存其响应,因请求体单向消耗导致 fetch 失败;cache.put() 对上传无效因其响应无重放价值;应改用 fetch + 预读 ArrayBuffer 构造可复用请求,并由前端控制离线队列与 sync 重发。

service worker如何拦截和缓存xml上传请求

Service Worker 能否拦截 XMLHttpRequest 的 POST 请求?

不能直接缓存上传请求的响应体,但可以拦截并阻止默认行为——关键在于:浏览器对 XMLHttpRequest(尤其是带 send(body) 的 POST)的请求体读取是单向且不可复用的。一旦你在 fetch 事件中调用 event.request.clone().arrayBuffer() 或类似方法,原始请求体就被消耗掉了,后续 fetch(event.request) 会失败并抛出 TypeError: Failed to execute 'fetch' on 'Window': Request body is already used。

为什么 cache.put() 对上传请求基本无效?

因为缓存的是响应,而 XML 上传这类请求的目标通常是服务端处理动作(如提交表单、触发任务),其响应往往无意义(200 OK 空体、204 No Content),或含动态时间戳/ID,不具备可重放性。强行缓存会导致:

  • 重复提交(用户刷新页面后 Service Worker 返回旧响应,但服务端已执行过)
  • 缓存击穿(响应体为空或极小,cache.put() 成功但无实际价值)
  • 请求体丢失导致 fetch 失败,降级为离线失败

真正可行的替代方案:用 fetch() + FormData + Request 构造可拦截的上传

必须放弃原生 XMLHttpRequest,改用 fetch() 发起上传,并确保请求体可被多次读取。核心是:不直接传原始 FormData 或 Blob,而是提前转为 ArrayBuffer 或 Uint8Array,再构造新 Request:

self.addEventListener('fetch', event => {
  if (event.request.method === 'POST' && event.request.url.includes('/upload')) {
    event.respondWith((async () => {
      try {
        // 1. 提前读取 body(只做一次)
        const bodyArray = await event.request.arrayBuffer();
        
        // 2. 构造可复用的新 Request(注意:headers 需手动复制,Content-Length 会自动计算)
        const newRequest = new Request(event.request.url, {
          method: 'POST',
          headers: Object.fromEntries(event.request.headers),
          body: bodyArray
        });

        // 3. 可选:先尝试缓存匹配(对上传场景通常跳过)
        // const cached = await caches.match(newRequest);
        // if (cached) return cached;

        // 4. 转发请求到网络
        const response = await fetch(newRequest);
        
        // 5. 缓存响应?仅当响应有明确重用价值(如上传后返回资源 URL)
        // if (response.status === 200) {
        //   const cache = await caches.open('uploads');
        //   await cache.put(newRequest, response.clone());
        // }

        return response;
      } catch (err) {
        return new Response('Upload failed', { status: 503 });
      }
    })());
  }
});

注意:event.request.arrayBuffer() 是唯一安全读取方式;用 text() 或 json() 会破坏二进制数据;FormData 实例无法被 clone() 后重复使用,必须转底层字节。

离线上传的兜底逻辑必须由前端主动控制

Service Worker 不适合自动重放上传请求。正确做法是:

  • 前端在发起 fetch('/upload', { method: 'POST', body: formData }) 前,先检查 navigator.onLine
  • 若离线,将序列化后的请求数据(URL、headers、body ArrayBuffer base64)存入 IndexedDB
  • Service Worker 中监听 sync 事件,在恢复联网后主动拉取待上传队列并重发
  • 避免在 fetch 事件里自动重试——用户可能已关闭页面,或数据已过期

真正的难点不在拦截,而在语义:上传不是 GET,它代表状态变更。缓存它的“结果”不如保证它的“送达”。fetch 事件里能做的只是可控转发,而非魔法缓存。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

花生AI
花生AI Hot

一款AI视频创作工具,主要用于B站推出的AI视频创作工具,适合需要提升相关任务效率的用户。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2235

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

3582

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

1196

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

4119

2025.09.10

pdf怎么转换成xml格式
pdf怎么转换成xml格式

将 pdf 转换为 xml 的方法:1. 使用在线转换器;2. 使用桌面软件(如 adobe acrobat、itext);3. 使用命令行工具(如 pdftoxml)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

4884

2024.04.01

xml怎么变成word
xml怎么变成word

步骤:1. 导入 xml 文件;2. 选择 xml 结构;3. 映射 xml 元素到 word 元素;4. 生成 word 文档。提示:确保 xml 文件结构良好,并预览 word 文档以验证转换是否成功。想了解更多xml的相关内容,可以阅读本专题下面的文章。

6337

2024.08.01

xml是什么格式的文件
xml是什么格式的文件

xml是一种纯文本格式的文件。xml指的是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。想了解更多相关的内容,可阅读本专题下面的相关文章。

2562

2024.11.28

Uvicorn 报错与问题解决教程
Uvicorn 报错与问题解决教程

本专题汇总了Uvicorn服务器常见问题与报错解决的教程合集,涵盖启动失败、端口占用、模块导入错误、事件循环冲突及热重载失效等典型故障的排查思路。同时整理了多进程与Worker配置、SSL/HTTPS证书报错、跨域与代理配置等实战解决方案,助你快速定位并解决Uvicorn运行中的各类问题。

0

2026.11.02

Uvicorn使用教程
Uvicorn使用教程

本专题汇总了Uvicorn使用教程与启动运行指南,涵盖其作为Python ASGI服务器的定位与特点,以及命令行启动(uvicorn main:app --reload)、参数配置(host/port/workers)、程序内嵌运行与Gunicorn结合部署等核心用法。同时整理了热重载调试、日志配置与生产环境部署优化等技巧,助你快速掌握Uvicorn的运行与配置。

0

2026.11.02

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn