【问题标题】:Can't access arrayBuffer on RangeRequest无法访问 RangeRequest 上的 arrayBuffer
【发布时间】:2019-01-10 23:53:44
【问题描述】:

尝试解决本文提到的问题:https://philna.sh/blog/2018/10/23/service-workers-beware-safaris-range-request/ 和这里: PWA - cached video will not play in Mobile Safari (11.4)

根本问题是我们无法在 Safari 上显示视频。这篇文章说它已经解决了这个问题,但似乎在 Chrome 上引起了另一个问题。我们解决方案的不同之处在于我们没有使用缓存。目前我们只想在我们的服务工作者中传递请求。实现如下所示:

self.addEventListener('fetch', function (event){
    if (event.request.cache === 'only-if-cached' && event.request.mode !== 'same-origin') {
        return;
    }

    if (event.request.headers.get('range')) {
        event.respondWith(returnRangeRequest(event.request));
    } else {
        event.respondWith(fetch(event.request));
    }
});

function returnRangeRequest(request) {
return fetch(request)
    .then(res => {
        return res.arrayBuffer();
    })
    .then(function(arrayBuffer) {
        var bytes = /^bytes\=(\d+)\-(\d+)?$/g.exec(
            request.headers.get('range')
        );
        if (bytes) {
            var  start = Number(bytes[1]);
            var end = Number(bytes[2]) || arrayBuffer.byteLength - 1;
            return new Response(arrayBuffer.slice(start, end + 1), {
                status: 206,
                statusText: 'Partial Content',
                headers: [
                    ['Content-Range', `bytes ${start}-${end}/${arrayBuffer.byteLength}`]
                ]
            });
        } else {
            return new Response(null, {
                status: 416,
                statusText: 'Range Not Satisfiable',
                headers: [['Content-Range', `*/${arrayBuffer.byteLength}`]]
            });
        }
    });
}

我们确实在范围请求获取时返回了一个数组缓冲区,但它的 byteLength 为零并且看起来是空的。范围标头实际上包含“bytes=0-”,后续请求有一个开始值,但没有结束值。

也许我们可以做一些特征检测来确定它是 chrome,我们可以定期调用 fetch 吗?我宁愿有一个适用于任何地方的解决方案。 res 也显示 type:"opaque" 所以也许这与它有关?不太确定接下来要看什么。如果我们无法解决 Chrome 的问题,我可能需要 Safari 的不同解决方案。

【问题讨论】:

  • 希望@milanio 会知道 :)

标签: google-chrome safari service-worker progressive-web-apps


【解决方案1】:

这似乎是不透明的反应。我没有意识到 fetch 默认是“nocors”。添加“cors”模式并覆盖范围标题似乎允许重写在 chrome 上工作。可悲的是,它仍然无法在 Safari 上运行,但我能够在正确设置 cors 值后访问 arrayBuffer。

这是我必须做出的改变:

var myHeaders = {};
return fetch(request, { headers: myHeaders, mode: 'cors', credentials: 'omit' })
    .then(res => {
        return res.arrayBuffer();
    })

服务器使用允许的标头进行响应很重要。例如

access-control-allow-methods: GET
access-control-allow-origin: *

【讨论】:

  • 没关系,这确实适用于 Safari,我只是设置了断点。
  • 嗨@UriahBlatherwick,你具体在哪里添加了这5行JS?
  • 恐怕我已经没有代码了。我认为这将是您在代理中返回获取响应的任何地方。整个事情虽然有点误导。我试图重新创建本质上是 noop 的东西,目标应该是完全跳过提取,因为它总是影响视频传输。我认为在我的代码中可能是这个被替换了:return fetch(request) .then(res => { return res.arrayBuffer(); })
猜你喜欢
  • 2018-09-27
  • 1970-01-01
  • 1970-01-01
  • 2013-10-02
  • 2016-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-20
相关资源
最近更新 更多