gpt4 book ai didi

javascript - 如何仅在 URL 加载后调用 revokeObjectURL?

转载 作者:行者123 更新时间:2023-12-04 00:57:38 30 4
gpt4 key购买 nike

我有一个网络应用程序。它在 Google Chrome 中运行,不需要在任何其他浏览器中运行。

我有在服务器上生成并在 AJAX 请求中发送回客户端的 PDF 数据。
我从 PDF 数据创建了一个 blob。
我使用 window.URL.createObjectURL 从 blob 创建一个 URL,然后将其加载到以前创建的用于显示 PDF 的窗口(我的 preview_window)中。

为了加载 URL,我设置了 preview_window.location.href。

我想调用 revokeObjectURL 以避免在窗口中生成和预览新的 PDF 时浪费越来越多的资源。
问题是在设置 preview_window.location.href 后立即调用它为时过早,并阻止了 PDF 的显示。因此,我想仅在加载 URL 后调用 revokeObjectURL。
为此,我尝试将 preview_window.onload 设置为回调,但它永远不会被调用。

我想知道:

  • 当窗口加载 URL 时是否可以触发回调,就像我试图做的那样?如何?
  • 是否有另一种方法可以确保及时调用 revokeObjectURL?

  • 如果在窗口完成加载 URL 时无法触发 revokeObjectURL,我可以在生成新 URL 之前立即撤消每个 URL。但如果可能的话,我宁愿在加载完成后立即撤销 URL。

    我准备了一个 html 文件,它很好地展示了这种情况:
    <html>
    <head>
    <title>Show PDF Demo</title>
    <script>
    var build_blob = function(mime_type, data) {
    var buf = new ArrayBuffer(data.length);
    var ia = new Uint8Array(buf);
    for (var i = 0; i < data.length; i++) ia[i] = data.charCodeAt(i);
    var blob = new Blob([ buf ], { type: mime_type });
    return blob;
    };

    window.onload = function(e) {
    document.getElementById('preview_button').onclick = function(e) {

    // open the window in the onclick handler so we don't trigger popup blocking
    var preview_window = window.open(null, 'preview_window');

    // use setTimeout to simulate an asynchronous AJAX request
    setTimeout(function(e) {
    var pdf_data = atob(
    "JVBERi0xLjQKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZwovT3V0bGluZXMgMiAwIFIKL1BhZ2Vz" +
    "IDMgMCBSCj4+CmVuZG9iagoyIDAgb2JqCjw8IC9UeXBlIC9PdXRsaW5lcwovQ291bnQgMAo+Pgpl" +
    "bmRvYmoKMyAwIG9iago8PCAvVHlwZSAvUGFnZXMKL0tpZHMgWzQgMCBSXQovQ291bnQgMQo+Pgpl" +
    "bmRvYmoKNCAwIG9iago8PCAvVHlwZSAvUGFnZQovUGFyZW50IDMgMCBSCi9NZWRpYUJveCBbMCAw" +
    "IDUwMCAyMDBdCi9Db250ZW50cyA1IDAgUgovUmVzb3VyY2VzIDw8IC9Qcm9jU2V0IDYgMCBSCi9G" +
    "b250IDw8IC9GMSA3IDAgUiA+Pgo+Pgo+PgplbmRvYmoKNSAwIG9iago8PCAvTGVuZ3RoIDczID4+" +
    "CnN0cmVhbQpCVAovRjEgMjQgVGYKMTAwIDEwMCBUZAooU01BTEwgVEVTVCBQREYgRklMRSkgVGoK" +
    "RVQKZW5kc3RyZWFtCmVuZG9iago2IDAgb2JqClsvUERGIC9UZXh0XQplbmRvYmoKNyAwIG9iago8" +
    "PCAvVHlwZSAvRm9udAovU3VidHlwZSAvVHlwZTEKL05hbWUgL0YxCi9CYXNlRm9udCAvSGVsdmV0" +
    "aWNhCi9FbmNvZGluZyAvTWFjUm9tYW5FbmNvZGluZwo+PgplbmRvYmoKeHJlZgowIDgKMDAwMDAw" +
    "MDAwMCA2NTUzNSBmCjAwMDAwMDAwMDkgMDAwMDAgbgowMDAwMDAwMDc0IDAwMDAwIG4KMDAwMDAw" +
    "MDEyMCAwMDAwMCBuCjAwMDAwMDAxNzkgMDAwMDAgbgowMDAwMDAwMzY0IDAwMDAwIG4KMDAwMDAw" +
    "MDQ2NiAwMDAwMCBuCjAwMDAwMDA0OTYgMDAwMDAgbgp0cmFpbGVyCjw8IC9TaXplIDgKL1Jvb3Qg" +
    "MSAwIFIKPj4Kc3RhcnR4cmVmCjYyNQolJUVPRg=="
    );

    /*
    Warning: for my Chrome (Version 44.0.2403.155 m), the in-built PDF viewer doesn't seem
    to work with a blob when this html page is loaded from the local filesystem. I have only
    got this to work when fetching this page via HTTP.
    */

    var pdf_blob = build_blob('application/pdf', pdf_data);

    var pdf_url = window.URL.createObjectURL(pdf_blob);

    preview_window.onload = function(e) {
    console.log("preview_window.onload called"); // never happens
    window.URL.revokeObjectURL(pdf_url);
    };

    preview_window.location.href = pdf_url;
    console.log("preview_window.location.href set");

    }, 500);
    };
    };
    </script>
    </head>
    <body>
    <button id="preview_button">Show Preview</button>
    </body>
    </html>

    虽然我上面的演示代码避免了它,但我确实为我的应用程序加载了 jQuery,所以如果这让事情变得更容易,我愿意使用它。

    我确实找到了 this question在搜索中,但在这种情况下,主窗口(“窗口”)被指向一个新的 URL,并且当在评论中询问窗口是否来自 window.open 是否有区别时,OP 从未得到响应。

    最佳答案

    如您所见,您无法设置 open()从开启者编辑窗口的 onload 事件。
    您必须在第二页中注入(inject)一些脚本,该脚本将调用它的 window.opener。职能。

    但由于您打开的是 pdf 文件,浏览器将重新解析整个页面,并且您注入(inject)的代码将消失。

    正如您在评论中发现的那样,解决方案是将 blob 的 url 注入(inject) iframe 中,然后等待此 iframe 的加载事件。

    方法如下:

    index.html

        <script>
    // The callback that our pop-up will call when loaded
    function imDone(url){
    window.URL.revokeObjectURL(url);
    }

    var build_blob = function(mime_type, data) {
    var buf = new ArrayBuffer(data.length);
    var ia = new Uint8Array(buf);
    for (var i = 0; i < data.length; i++) ia[i] = data.charCodeAt(i);
    var blob = new Blob([ buf ], { type: mime_type });
    return blob;
    };
    var preview_window=null;
    window.onload = function(e) {
    document.getElementById('preview_button').onclick = function(e) {
    if(preview_window===null || preview_window.closed){
    // open the window in the onclick handler so we don't trigger popup blocking
    preview_window = window.open('html2.html', 'preview_window');
    }
    // avoid reopening the window since it may cache our last blob
    else preview_window.focus();

    // use setTimeout to simulate an asynchronous AJAX request
    setTimeout(function(e) {
    var pdf_data = /* Your pdf data */

    var pdf_blob = build_blob('application/pdf', pdf_data);

    var pdf_url = window.URL.createObjectURL(pdf_blob);
    // Simple loop if our target document is not ready yet
    var loopLoad = function(url){
    var doc = preview_window.document;
    if(doc){
    var iframe = doc.querySelector('iframe');
    if(iframe)iframe.src = url;
    else setTimeout(function(){loopLoad(url);},200);
    }
    else setTimeout(function(){loopLoad(url);},200)
    };
    loopLoad(pdf_url);

    }, 0);
    };
    };
    </script>

    html2.html
    <html>
    <head>
    <title>Iframe PDF Demo</title>
    <style>
    body, html, iframe{margin:0; border:0}
    </style>
    </head>
    <body>
    <iframe width="100%" height="100%"></iframe>
    <script>
    document.querySelector('iframe').onload = function(){
    //first check that our src is set
    if(this.src.indexOf('blob')===0)
    // then call index.html's callback
    window.opener.imDone(this.src);
    }
    </script>
    </body>
    </html>

    Live Demo

    关于javascript - 如何仅在 URL 加载后调用 revokeObjectURL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32180732/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com