【问题标题】:Opening and closing a new tab when downloading下载时打开和关闭新标签页
【发布时间】:2012-12-04 03:18:58
【问题描述】:

在很多网站上(Dropbox 就是一个很好的例子),当你点击一个文档来下载它时,它会打开一个新的窗口/标签,然后出现下载提示,并且标签/窗口立即关闭自身(同时提示保持打开状态)。

如何使用 javascript 复制此行为?

我认为一种方法是检测下载提示的外观,然后使用window.close()。但是,我不确定如何检测该特定提示。

首选跨浏览器解决方案,但非常感谢任何可以在 Firefox 中运行的解决方案。

澄清

  1. 我在 Greasemonkey 脚本中执行此操作
  2. 在新选项卡中打开的“链接”不一定是指向文档的直接链接。有时它是一个简单的页面,在后台开始下载。我指的是具有特殊“下载”页面的网站类型......那些说“您的下载将很快开始,如果没有开始,请点击此处”之类的网站。

更多说明:关于上面说明 2 中提到的网站类型,我要做的是单击下载链接,在新窗口中加载该特定下载页面,然后下载开始后关闭窗口。

【问题讨论】:

  • 所以,除非我忘记了,否则他们使用window.open,将其指向一个 URL(要下载的内容),响应中的 HTTP 标头是特定于用户下载的.一旦响应到达浏览器,它就会自动关闭——你不必做任何事情。我看看能不能找到我用过的例子
  • 您使用的是特定的网络服务器吗?
  • 例如,你需要使用类似这样的东西 - stackoverflow.com/questions/8897458/… - 取决于你的网络服务器
  • 我不完全确定你在问什么...你的意思是我要在哪个网站上实现它?我实际上只是在做一个小 Greasemonkey 脚本,我想在几个不同的网站上实现这种行为。
  • 那么您将要允许用户下载的文件存储在哪里?您必须将文件存储在某处,然后将它们提供给用户。使它们可用是不够的 - 您必须通过 HTTP 提供内容并设置适当的标头以使其按照您想要的方式运行。我想我不确定油脂猴是如何工作的

标签: javascript tabs greasemonkey


【解决方案1】:

你想要的有三个基本部分:

  1. 您必须拦截下载链接。
  2. 您必须在单击时将链接发送到新选项卡,而不仅仅是使用target="_blank" 修改它。该选项卡必须使用 javascript 打开,以便在时机成熟时允许 javascript 将其关闭。
  3. 您的脚本还必须在“弹出”选项卡上运行/处理,以便检测何时关闭弹出窗口。

关于这个讨论,参考this test page at jsFiddle它的结构是这样的:

<div id="downloadLinks">
  <ul>
    <li><a class="dwnPageLink" href="http://fiddle.jshell.net/cDTKj/show/">
            Test file, download page at jsFiddle
        </a>
    </li>
    <li><a class="dwnPageLink" href="http://dw.com.com/redir...">
            TextPad (a great text editor), download page at CNET / Download
        </a>
    </li>
  </ul>
</div>

a.dwnPageLink 链接每个都打开一个“下载页面”——在短暂延迟后自动开始文件下载。


截取下载链接(a.dwnPageLink):

我们像这样拦截链接:

$("#downloadLinks a.dwnPageLink").each (interceptLink);

function interceptLink (index, node) {
    var jNode   = $(node);
    jNode.click (openInNewTab);
    jNode.addClass ("intercepted");
}

请注意,我们还添加了一个 CSS 类,以便我们可以快速查看哪些链接受到了影响。
openInNewTab 将在下面详细说明。它必须同时打开一个选项卡,并且必须停止正常的链接操作。


将链接发送到新标签页:

我们必须使用window.open() 来处理链接。如果页面不是通过window.open打开的,我们的脚本将无法关闭它。

请注意,GM_openInTab() 不能使用,因为它不会导致正确设置 window.opener,否则不会提供关闭打开的选项卡的机制。

新标签页在openInNewTab 中启动,如下所示:

function openInNewTab (zEvent) {
    //-- Optionally adjust the href here, if needed.
    var targURL     = this.href;
    var newTab      = window.open (targURL, "_blank");

    //--- Stop the link from doing anything else.
    zEvent.preventDefault ();
    zEvent.stopPropagation ();
    return false;
}


处理“弹出”标签:

无法从启动页面监视文件对话框。所以我们必须将脚本设置为也在“弹出”选项卡上运行。相应地添加@include 指令。

我们脚​​本的弹出部分可以通过监视beforeunload 事件来检测文件对话框。浏览器将在打开文件对话框之前触发beforeunload 事件(也就是在选项卡关闭之前,但我们可以忽略它)。

但是,我们不能只在对话框出现时关闭选项卡。这样做也会关闭对话框。所以我们添加了一个小的时间延迟和一个“确认”对话框,以便选项卡将保持打开状态,直到文件对话框关闭。要清除“确认”对话框,只需再按一次Enter(或单击确定)。

代码如下所示:

$(window).bind ("beforeunload",  function (zEvent) {
    //-- Allow time for the file dialog to actually open.
    setTimeout ( function () {
            /*-- Since the time it takes for the user to respond
                to the File dialog can vary radically, use a confirm
                to keep the File dialog open long enough for the user 
                to act.
            */
            var doClose = confirm ("Close this window?");
            if (doClose) {
                window.close ();
            }
        },
        444 // 0.444 seconds
    );
} );


注意:

  1. 由于脚本将在“列表”页面和“下载”页面上运行,我们可以通过检查window.opener 来判断哪个是哪个。在由 javascript 打开的页面上,这将具有非空值。
  2. 这个问题没有询问在后台加载选项卡。可以做到这一点,取得不同程度的成功,但涉及更多。为此提出一个新问题。


完整的脚本:

此脚本适用于 the test pageCNET / Download pages

// ==UserScript==
// @name        _Download page, auto closer
// @namespace   _pc
// ******** Includes for "List pages" that have the links we might click...
// @include     http://YOUR_SERVER.COM/YOUR_LIST-PAGE_PATH/*
// @include     http://jsbin.com/ozofom/*
// @include     http://fiddle.jshell.net/qy3NP/*
// @include     http://download.cnet.com/*
// ******** Includes for "Popup pages" that do the actual downloads...
// @include     http://YOUR_SERVER.COM/YOUR_POPUP-PAGE_PATH/*
// @include     http://fiddle.jshell.net/cDTKj/*
// @include     http://dw.com.com/redir?*
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @grant       GM_addStyle
// @grant       GM_openInTab
// ==/UserScript==
/*- Important: The @include or @match directives must for for both the pages
    that list the download links, AND the pages that do the actual downloading.

    The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/

var bPageNotOpenedByJavascript = window.opener ? false : true;
if (bPageNotOpenedByJavascript) {
    /***** "Normal" page, which might contain links to special download pages.
    */
    //--- Intercept links to the download pages:
    // For our jsFiddle Test page:
    $("#downloadLinks a.dwnPageLink").each (interceptLink);

    // For CNET/Download:
    $("#downloadLinks div.dlLinkWrapper a").each (interceptLink);

    GM_addStyle ( "                                 \
        a.intercepted {                             \
            background:         lime;               \
        }                                           \
    " );
}
else {
    /***** Page opened by JS in either a popup or new tab.
        This was *most likely* done by us, using window.open.
    */
    $(window).bind ("beforeunload",  function (zEvent) {
        //-- Allow time for the file dialog to actually open.
        setTimeout ( function () {
                /*-- Since the time it takes for the user to respond
                    to the File dialog can vary radically, use a confirm
                    to keep the File dialog open long enough for the user
                    to act.
                */
                var doClose = confirm ("Close this window?");
                if (doClose) {
                    window.close ();
                }
            },
            444 // 0.444 seconds
        );
    } );
}

function interceptLink (index, node) {
    var jNode   = $(node);
    jNode.click (openInNewTab);
    jNode.addClass ("intercepted");
}

function openInNewTab (zEvent) {
    //-- Optionally adjust the href here, if needed.
    var targURL     = this.href;
    var newTab      = window.open (targURL, "_blank");

    //--- Stop the link from doing anything else.
    zEvent.preventDefault ();
    zEvent.stopPropagation ();
    return false;
}

【讨论】:

  • @Nexen,您使用的是 Greasemonkey 版本 4 或更高版本吗?如果是这样,请切换到 Tampermonkey 并重试。
  • 我说的是这个链接fiddle.jshell.net/qy3NP/show,而不是插件解决方案。无论如何,有这个工作链接:jsfiddle.net/g5Gn5
  • @Nexen,好的,谢谢。几天后我会重新审视这个答案。
【解决方案2】:

你可以通过设置target="_blank"来简单地使用&lt;a&gt;标签

<a href="http://jqueryui.com/resources/download/jquery-ui-1.9.2.custom.zip" target="_blank">Download</a>​

演示:http://jsfiddle.net/g5Gn5/

一旦出现文件对话框,它将打开一个新窗口/选项卡并自动关闭。

【讨论】:

  • 这只是因为响应设置了一个用于下载项目的标头(或者因为它是一个压缩文件)。通常,它会在浏览器中显示其内容。 _blank 只是在新窗口/标签中打开它,但对它的打开方式没有影响
  • 是的,它是一个压缩文件,我的演示工作。感谢您的反对。
  • 哈哈很好,仅仅因为它适用于一个文件并不意味着它是一个通用的解决方案。正如我所指出的,您不能只使用_blank...尝试使用ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js
  • @Ian 我无法提供完整的解决方案。您需要设置header 才能下载js, html, txt 或任何文本格式的文件。
  • 这个解决方案对我不起作用。请参阅我在原始问题中的说明。
【解决方案3】:

只需使用这个简单的解决方案:

<a href="linkToDownloadFile.html" onclick="download('linkToDownloadFile.html'); return false;">

<script>
    function download(link){
      var popout = window.open(link);
      window.setTimeout(function(){
         popout.close();
      }, 2000);
    }
</script>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-11
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多