【问题标题】:Failed to execute 'atob' on 'Window'无法在“窗口”上执行“atob”
【发布时间】:2014-04-29 23:41:51
【问题描述】:

当用户按下ctrl + s 键但 Chrome 崩溃时,我正在尝试将我的 HTML 文件保存在 Chrome 中。

(我只想下载我的 HTML 文件的源代码)

我读到这是因为我的文件大于 1.99M..

第一次尝试(在我知道 Chrome 崩溃之前):

function download(filename, text) {
    var pom = document.createElement('a');
    pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    pom.setAttribute('download', filename);
    pom.click();
}

download('test.html', "<html>" + document.getElementsByTagName('html')[0].innerHTML + "</html>");

第二次尝试,在阅读了崩溃的消息后,我使用了blob

function dataURItoBlob(dataURI) {
    var byteString = atob(dataURI.split(',')[1]);

    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]

    var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(ab);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    var bb = new BlobBuilder();
    bb.append(ab);
    return bb.getBlob(mimeString);
}

function download(dataURI) {
    var blob = dataURItoBlob(dataURI);
    var url  = window.URL.createObjectURL(blob);
    window.location.assign(url);
}

download("<html>" + document.getElementsByTagName('html')[0].innerHTML + "</html>")

这里我得到了错误:Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.

我不知道,但我读到我需要将我的字符串编码为 base64:How can you encode a string to Base64 in JavaScript?

有 148 票的答案。我将其粘贴到我的代码中,但不知道如何继续。

我应该在哪里调用它以及如何调用它?我可以在我保存的文件上命名吗?

我认为我需要这样做:

download(_utf8_decode("<html>" + document.getElementsByTagName('html')[0].innerHTML + "</html>"))

【问题讨论】:

  • 你到底想达到什么目的?
  • 我有一个html文件..有可以动态插入的输入..(用户可以在这些输入中写文本)..写完文本后,我想保存页面与他的变化,为了让他继续他离开的地方..
  • 为什么不只保存输入然后将它们嵌入到下一页?
  • 我没听懂你的意思.. 用户可以在他离开的地方继续吗?如果他可以,请建议我..假设我有:jsfiddle.net/jaredwilli/tZPg4/4 并且我添加了 3 个输入..我怎样才能让用户关闭文件然后继续他离开的点(还有 3 个输入)..(假设我只有带有大数据的 html 文件.. 4 mb)
  • 尝试找到(在您的代码中)重定向路径,并关注它,也许在您的函数 download() 中...在您的代码中搜索一点,查看 URI 定义!这两种环境都发生过吗?还是仅在您尝试部署时用于生产?

标签: javascript jquery html


【解决方案1】:

我有同样的错误,我发现的修复是在 messinging.usePublicVapidKey('PAIR KEY') 我正在使用服务器密钥,它需要“配对密钥”。你可以在https://console.firebase.google.com/project/_/settings/cloudmessaging/找到该信息

所以该函数的值是控制台中的对键,我很困惑并把服务器键?‍♂️ 并创建了 Uncaught DOMException: Failed to execute 'atob' on 'Window':.

【讨论】:

    【解决方案2】:

    您不需要将整个编码字符串传递给 atob 方法,您需要将编码字符串拆分并将所需的字符串传递给 atob 方法

    const token= "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJob3NzYW0iLCJUb2tlblR5cGUiOiJCZWFyZXIiLCJyb2xlIjoiQURNSU4iLCJpc0FkbWluIjp0cnVlLCJFbXBsb3llZUlkIjoxLCJleHAiOjE2MTI5NDA2NTksImlhdCI6MTYxMjkzNzA1OX0.8f0EeYbGyxt9hjggYW1vR5hMHFVXL4ZvjTA6XgCCAUnvacx_Dhbu1OGh8v5fCsCxXQnJ8iAIZDIgOAIeE55LUw"
    console.log(atob(token.split(".")[1]));

    【讨论】:

      【解决方案3】:

      就我而言,我疯了,因为要解码的字符串没有任何问题,因为我可以在在线工具上成功解码它。 直到我发现你首先要decodeURIComponent你正在解码的东西,就像这样:

      atob(decodeURIComponent(dataToBeDecoded));
      

      【讨论】:

        【解决方案4】:

        BlobBuilder 已过时,请改用Blob constructor

        URL.createObjectURL(new Blob([/*whatever content*/] , {type:'text/plain'}));
        

        这会返回一个 blob URL,然后您可以在锚点的 href 中使用它。您还可以修改锚点的download 属性来操作文件名:

        <a href="/*assign url here*/" id="link" download="whatever.txt">download me</a>
        

        Fiddled。如果我没记错的话,对受信任的非用户发起的下载有任意限制;因此,我们将坚持使用被视为充分由用户发起的链接点击:)

        更新:保存当前文档的 html 实际上非常简单!每当单击我们的交互式链接时,我们将使用相关的 blob 更新其 href。执行点击绑定事件后,就是要导航到的下载地址!

        $('#link').on('click', function(e){
          this.href = URL.createObjectURL(
            new Blob([document.documentElement.outerHTML] , {type:'text/html'})
          );
        });
        

        Fiddled again.

        【讨论】:

        • 感谢您的评论.. 不幸的是,它保存了我更改之前的 html.. (它不保存我输入的文本).. 我认为你是如此接近.. 我没有在我看到你的 jsfiddle 之前无法成功保存 html.. 请再次帮助我:) 例如:jsfiddle.net/7NqKb/3 请输入文本并按download me
        • 我试过:document.documentElement.outerHTML、document.documentElement.innerHTML、document.getElementsByTagName('html')[0].innerHTML.. 但它不记得添加的输入:/
        • @AlonShmiel:请记住,当更改输入文本等时,您不是在修改 html,而是在修改 DOM!您必须将 DOM 序列化回 html/xhtml,因为 innerHTML/outerHTML 不反映突变。
        • @AlonShmiel - 我认为您可以在更新下载链接之前运行类似 Array.prototype.forEach.call(document.querySelector('input'), function (e) { e.setAttribute('value', e.value); }); 的内容(textareaselect 类似)。
        【解决方案5】:

        这里我得到了错误:Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.

        因为您没有传递 base64 编码的字符串。看看你的函数:downloaddataURItoBlob 出于某种原因都需要 data URI;但是,在您的示例中,您将纯 html 标记字符串传递给 download

        不仅 HTML 作为 base64 无效,而且您在其上调用 .split(',')[1] 将产生 undefined - 并且 "undefined" 也不是有效的 base64 编码字符串。

        我不知道,但我读到我需要将我的字符串编码为 base64

        这对我来说没有多大意义。您想以某种方式对其进行编码,然后才对其进行解码?

        我应该调用什么以及如何调用?

        download 函数的接口改回它接收filenametext 参数的位置。

        请注意,BlobBuilder 不仅支持附加整个字符串(因此您不需要创建那些 ArrayBuffer 的东西),而且不推荐使用 Blob constructor

        我可以在我保存的文件上命名吗?

        是的。不要使用Blob 构造函数,而是使用File 构造函数。

        function download(filename, text) {
            try {
                var file = new File([text], filename, {type:"text/plain"});
            } catch(e) {
                // when File constructor is not supported
                file = new Blob([text], {type:"text/plain"});
            }
            var url  = window.URL.createObjectURL(file);
            …
        }
        
        download('test.html', "<html>" + document.documentElement.innerHTML + "</html>");
        

        请参阅 JavaScript blob filename without link 了解如何处理该对象 url,仅将当前位置设置为它不起作用。

        【讨论】:

        • 谢谢..我得到:构造'文件'失败:非法构造函数我正在检查它..
        • 我没有测试代码,抱歉。可能File 构造函数太新,无法在(您的)浏览器中支持,MDN doesn't mention it 这就是我链接规范草案的原因。尝试使用Blob 构造函数(但是没有文件名),其中is supported in all browsers
        • 它打开了一个页面,他的标题是:Blob:8db3e422-8597-4beb-....,内容是我所有的html源,并且有一条消息'脚本没有响应'..它在chrome中写给我和火狐..
        【解决方案6】:

        这是一个更新的小提琴,其中用户的输入自动保存在本地存储中。每次重新运行小提琴或刷新页面时,都会恢复以前的状态。 这样你就不需要提示用户保存,它只是自己保存。

        http://jsfiddle.net/tZPg4/9397/

        堆栈溢出需要我包含一些带有 jsFiddle 链接的代码,所以请忽略 sn-p:

        localStorage.setItem(...)
        

        【讨论】:

        • 我不明白这是如何回答这个问题的。 OP 确实想将当前 html 作为 file 下载,而不是将某些内容存储在本地存储中?
        • 但这可能是 OP 根据 cmets 尝试完成的任务的替代方案
        • 对 - 当您考虑到此评论时,我认为我的回答是合适的:我想保存包含他的更改的页面,以便让他继续他离开的地方。
        • 感谢您的评论..我有很多意见,所以您的解决方案对我来说似乎太难了..但如果我没有找到其他解决方案,您的解决方案将帮助我..谢谢为您的评论! :]
        • 恐怕只有我的解决方案可以解决您的问题:保存输入状态
        猜你喜欢
        • 1970-01-01
        • 2021-03-25
        • 2020-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-26
        相关资源
        最近更新 更多