【问题标题】:How can I export cached files saved in a browser using CacheStorage?如何使用 CacheStorage 导出保存在浏览器中的缓存文件?
【发布时间】:2021-03-29 14:46:12
【问题描述】:

我有一个网站,它使用 CacheStorage API 来使用 Service Worker 保存各种文件。由于我无法控制的原因,这些文件中有很多已经从它们加载的服务器中丢失了。但是,我刚刚意识到,数百个文件已在本地缓存在浏览器中,该浏览器多年来一直访问该站点(幸运的是,该站点本身并没有正确清除缓存)。我可以使用 chrome 的开发工具预览文件,但是当我点击“下载”时,它会尝试从服务器(不再存在)下载副本,而不是给我本地缓存的版本。

一次性导出这些文件的最简单方法是什么(记住有几百个)?我可以完全访问运行浏览器的计算机,以及运行站点/服务人员的域。它不需要是一个漂亮的解决方案,因为一旦文件恢复,我计划学习大量课程以防止将来发生类似的事情。

【问题讨论】:

    标签: google-chrome-devtools service-worker recovery cachestorage


    【解决方案1】:

    CacheStorage API 可以从普通网页 JavaScript 以及 service worker 访问,因此如果您在访问 window.caches 的服务器上创建网页,您应该能够从缓存中获取内容并做你想做的。一旦你有了cache.keys(),你就可以遍历它并使用match(),它会返回该请求的响应。然后,您可以将它们打印出来进行复制和粘贴(可能不太理想),将每个文件发布到保存它们的服务器,或类似的操作。

    这是我在 traintimes.org.uk 上的一些普通 JS;只是为了显示离线页面列表,但如果需要,它可能会获取实际的缓存条目。

    <script>
    // Open the page cache
    caches.open("pages")
        // Fetch its keys (cached requests)
        .then(cache => cache.keys())
        // We only want the URLs of each request
        .then(reqs => reqs.map(r => r.url))
        // We want most recent one first (reverse is in-place)
        .then(urls => (urls.reverse(), urls))
        // We don't care about the domain name
        .then(urls => urls.map(u => u.replace(/^.*?uk/, '')))
        // We want them to be clickable links
        .then(urls => urls.map(u => [
            '<a href="', u, '">',
            u.replace(/\?cookie=[^;&]*/, ''),
            '</a>'].join("")))
        // We want them to be visible on the page
        .then(urls =>
            document.getElementById('offline-list').innerHTML =
                '<li>' + urls.join('</li><li>') + '</li>'
        );
    </script>
    

    【讨论】:

    • 感谢 Matthew - 它真的很有帮助!不幸的是,我忽略了一个细节(我后来才意识到它是相关的)是有问题的文件来自不同的域并且没有设置任何 CORS 标头。 ? 因此,它们被视为“不透明”请求,因此我无法使用 javascript 访问正文。但如果不是这样的话,你的方法会很棒。
    【解决方案2】:

    添加到 CacheStorage API 的响应存储在磁盘上。例如,Mac OSX 上的 chrome 将它们存储在 ~/Library/Application Support/Google/Chrome/Default/Service Worker/CacheStorage。在此目录中,每个域都有一个目录,在这些目录中,该域使用的每个特定缓存都有单独的目录。这些目录的名称(在两个级别上)似乎不是人类可读的,因此您可能需要搜索内容以找到您要查找的特定缓存。

    在每个缓存的目录中,每个响应都保存在不同的文件中。这些是二进制文件,包含各种信息,包括请求的 URL(靠近顶部)和 HTTP 响应标头(接近末尾)。在这些之间,您会找到 HTTP 响应的正文。

    提取正文并将其保存到可在其他地方使用的文件的确切逻辑将根据 URL 架构、文件格式等而有所不同。这个 bash 脚本对我有用:

    #!/bin/bash
    
    mkdir -p export
    for file in *_0
    do
        output=`LC_ALL=C sed -nE 's%^.*/music/images/artists/542x305/([^\.]*\.jpg).*%\1%p;/jpg/q' $file`
        if [ -z "$output" ]
        then
            echo "file $file missing music URL"
            continue
        fi
    
        if [[ $(LC_ALL=C sed -n '/x-backend-status.*404/,/.*/p' $file) ]]
        then
            echo "$file returned a 404"
            continue
        fi
    
        path="export/$output"
    
        cat $file | LC_ALL=C sed -n '/music\/images\/artists/,$p' | LC_ALL=C sed 's%^.*/music/images/artists/542x305/[^\.]*\.jpg%%g' | LC_ALL=C sed -n '/GET.*$/q;p' > $path
        echo "$file -> $path"
    done
    

    【讨论】:

      猜你喜欢
      • 2016-07-08
      • 1970-01-01
      • 2015-05-09
      • 1970-01-01
      • 2021-07-29
      • 2012-07-15
      • 2010-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多