【问题标题】:How to trigger a file download when clicking an HTML button or JavaScript单击 HTML 按钮或 JavaScript 时如何触发文件下载
【发布时间】:2012-07-22 04:06:08
【问题描述】:

这太疯狂了,但我不知道该怎么做,而且由于这些词很常见,很难在搜索引擎上找到我需要的东西。我想这应该很容易回答。

我想要一个简单的文件下载,与此相同:

<a href="file.doc">Download!</a>

但我想使用 HTML 按钮,例如以下任一:

<input type="button" value="Download!">
<button>Download!</button>

同样,是否可以通过 JavaScript 触发简单下载?

$("#fileRequest").click(function(){ /* code to download? */ });

我绝对不是在寻找一种方法来创建一个看起来像按钮的锚,使用任何后端脚本,或者弄乱服务器标题或 mime 类型。

【问题讨论】:

  • 感谢您“如何在 javascript 中触发文件下载”将为任何未来的搜索者提供更快的答案。
  • 你在最后一段中的限制对我来说没有多大意义。如果您愿意接受使用 JavaScript(因为您这么说)或需要更改 DOM 结构(就像您接受的那个)的答案,为什么不也将锚定样式设置为按钮?我无法想象前两个会很好但作为按钮的锚会出现问题的场景。

标签: javascript html download


【解决方案1】:

您可以使用 HTML5 download 属性触发下载。

<a href="path_to_file" download="proposed_file_name">Download</a>

地点:

  • path_to_file 是解析为same origin 上的 URL 的路径。 这意味着页面和文件必须共享相同的域、子域、协议(HTTP 与 HTTPS)和端口(如果指定)。例外情况是 blob:data:(始终有效)和 file:(永远无效)。
  • proposed_file_name 是要保存到的文件名。如果为空,则浏览器默认使用文件名。

文档:MDNHTML Standard on downloadingHTML Standard on downloadCanIUse

【讨论】:

  • 不适用于 Safari 和某些 IE 版本
  • 使用downloadtarget="_blank" 的组合似乎足以涵盖大多数用例。理解download的浏览器会将其视为下载,否则会在新标签页中打开。
  • 如何将其应用于 button 对象,而不仅仅是 a 标签
  • 实际上这仅适用于与 MDN 文档中提到的来源相同的 url。如果我们正在寻求开发通用解决方案,这是一个巨大的限制
  • 问题是明确要求使用按钮而不是链接
【解决方案2】:

对于你可以做的按钮

<form method="get" action="file.doc">
   <button type="submit">Download!</button>
</form>

【讨论】:

  • 不能作为触发器工作,只是重定向到 url 作为 'a' 标记。
  • 这个效果更好:下载
  • @kscius 即使在今天,IE 11 也不支持下载属性(Edge 现在支持它),Safari 也不支持它。 2012 年最初发布答案时,任何主流浏览器都不支持它。
  • 拥有一个带有按钮样式的锚点和一个带有按钮的表单有什么区别?
  • 这不会必然触发下载。它只是让浏览器导航到file.doc。这是否导致 file.doc 被下载或在浏览器中显示为页面取决于服务器在提供 file.doc 时返回的标头以及浏览器能够呈现的文件类型。
【解决方案3】:

HTML:

<button type="submit" onclick="window.open('file.doc')">Download!</button>

【讨论】:

  • 如果我想下载一个xml文件怎么办?
  • 感谢您的代码。我已经测试过,它可以在IE、Chrome、Firefox中运行。
  • 如果您有浏览器可以接受的文件,例如 PDF,它将在新选项卡中打开,而不是显示下载对话框。
  • window.open 会在浏览器中触发弹出窗口阻止,因此不推荐使用。您可以使用 window.location = 'path' ,尽管这会转到同一浏览器窗口中的位置。
  • 这不一定会触发下载。它只是让浏览器导航到file.doc。这是否导致 file.doc 被下载或在浏览器中显示为页面取决于服务器在服务file.doc 时返回的标头以及浏览器能够呈现的文件类型。
【解决方案4】:

一个简单的JS解决方案:

function download(url) {
  const a = document.createElement('a')
  a.href = url
  a.download = url.split('/').pop()
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
}

【讨论】:

  • @NicholasKyriakides 让我想起了这颗宝石:image.ibb.co/dtkUWJ/Selection_002.png
  • @BryanLarsen 你是对的,Firefox 不允许在不先将元素添加到 body 的情况下这样做。谢谢,更新答案
  • 下载完成后有没有办法触发javascript函数?只是尝试在下载开始后显示一条消息,并在下载完成后删除该消息。
  • @mohitbansal (un) 幸运的是没有,因为它在浏览器级别
  • 这是最好的解决方案,应该被接受。
【解决方案5】:

使用 jQuery:

$("#fileRequest").click(function() {
    // hope the server sets Content-Disposition: attachment!
    window.location = 'file.doc';
});

【讨论】:

  • 完美,谢谢。您是否碰巧知道大多数服务器是否会默认将 Content-Disposition 设置为“附件”?
  • 没有“最多”。这完全取决于。不要依赖它被设置。
  • 这个问题一直让我发火,这是唯一有效的选项(并且受 IE 支持)。我将为像我这样的任何 n00bs 添加设置 Content-Disposition,您所要做的就是:
  • 没有 jquery。期间。
  • 如果您尝试下载图像,这不起作用,它会在浏览器中打开图像
【解决方案6】:

您可以使用不可见 iframe 的“技巧”来做到这一点。当您为其设置“src”时,浏览器的反应就像您单击具有相同“href”的链接一样。与表单解决方案相反,它使您能够嵌入额外的逻辑,例如在超时后激活下载,满足某些条件等。

它也很安静,没有像使用window.open时那样闪烁的新窗口/标签。

HTML:

<iframe id="invisible" style="display:none;"></iframe>

Javascript:

function download() {
    var iframe = document.getElementById('invisible');
    iframe.src = "file.doc";
}

【讨论】:

  • 确实如此,至少如果你真的将 iframe 应用到 document.body 的话。
  • 这似乎在 Chrome 中不起作用,尽管它曾经可以工作。我想知道它是否会在不同版本的 Chrome 中间歇性停止工作。
  • 适用于 Chrome 版本 61.0.3163.100(官方构建)(64 位)
  • 不适用于 Firefox v57 中的图像。它只是在 iframe 中呈现图像。
  • 如果文件属于浏览器知道如何呈现自己的类型,这将静默失败(除非服务器返回一个 Content-Disposition 标头指示应该下载文件)。
【解决方案7】:

引导版本

<a class="btn btn-danger" role="button" href="path_to_file"
   download="proposed_file_name">
  Download
</a>

记录在 in Bootstrap 4 docs,并且也可以在 Bootstrap 3 中使用。

【讨论】:

  • 这与 Bootstrap 唯一有关的是类名,它只是 HTML5 的强大功能。
  • 问题是明确询问如何使用按钮而不是链接来做到这一点。
  • 如果您对引导程序一无所知,您会发现它是一个按钮。
【解决方案8】:

我认为这是您正在寻找的解决方案

<button type="submit" onclick="window.location.href='file.doc'">Download!</button>

我有一个案例,我的 Javascript 生成了一个 CSV 文件。由于没有远程 URL 下载它,我使用以下实现。

downloadCSV: function(data){
    var MIME_TYPE = "text/csv";

    var blob = new Blob([data], {type: MIME_TYPE});
    window.location.href = window.URL.createObjectURL(blob);
}

【讨论】:

  • on 404 -> 页面更改为 404 错误页面。与其他 location.href 解决方案中所述的问题相同。
  • 这(至少是第一个实现)不一定会触发下载。它只是使浏览器导航到file.doc。这是否导致 file.doc 被下载或在浏览器中显示为页面取决于服务器在为 file.doc 提供服务时返回的标头以及浏览器能够呈现的文件类型。
【解决方案9】:

您可以隐藏下载链接并让按钮点击它。

<button onclick="document.getElementById('link').click()">Download!</button>
<a id="link" href="file.doc" download hidden></a>

【讨论】:

  • 为了在 Firefox 中工作,资源必须与文档在同一个域中。设置 CORS 标头没有有帮助。
  • 永远不要这样做
【解决方案10】:

怎么样:

<input type="button" value="Download Now!" onclick="window.location = 'file.doc';">

【讨论】:

  • 这不起作用,例如,如果您的文件是图像,因为它只会在浏览器中打开。
  • 会出现另一个问题,即如果文件丢失,它会将整个页面导航到 404 页面
  • 它在 2020 年完美运行(对于每个文件),它是所有解决方案中最简单的。太棒了!
  • 这不一定会触发下载。它只是使浏览器导航到file.doc。这是否导致 file.doc 被下载或在浏览器中显示为页面取决于服务器在提供 file.doc 时返回的标头以及浏览器能够呈现的文件类型。
【解决方案11】:

您好,我只包含“下载”这个词,效果很好。

<a href="file.pdf" download>Download</a>

所以在javascript中你可以使用如下:

function onStartedDownload(id) {
  console.log(`Started downloading: ${id}`);
}

function onFailed(error) {
  console.log(`Download failed: ${error}`);
}

var downloadUrl = "https://example.org/image.png";

var downloading = browser.downloads.download({
  url : downloadUrl,
  filename : 'my-image-again.png',
  conflictAction : 'uniquify'
});

downloading.then(onStartedDownload, onFailed);

【讨论】:

    【解决方案12】:

    如果您正在寻找一个普通的 JavaScript(没有 jQuery)解决方案并且不使用 HTML5 属性,您可以试试这个。

    const download = document.getElementById("fileRequest");
    
    download.addEventListener('click', request);
    
    function request() {
        window.location = 'document.docx';
    }
    .dwnld-cta {
        border-radius: 15px 15px;
        width: 100px;
        line-height: 22px
    }
    <h1>Download File</h1>
    <button id="fileRequest" class="dwnld-cta">Download</button>

    【讨论】:

    • 这不一定会触发下载。它只是使浏览器导航到file.doc。这是否导致 file.doc 被下载或在浏览器中显示为页面取决于服务器在为 file.doc 提供服务时返回的标头以及浏览器能够呈现的文件类型。
    【解决方案13】:

    在我的测试中,只要您使用相对链接,以下内容适用于所有文件类型和浏览器:

    <a href="/assets/hello.txt" download="my_file.txt"><button>Download 2</button></a>
    
    • /assets/hello.txt 只是我网站上的相对路径。将其更改为您自己的相对路径。
    • my_file.txt 是您希望文件在下载时被调用的名称。

    说明

    我注意到很多答案下都有 cmets 说浏览器只会尝试打开文件本身而不是根据文件类型下载它。我发现这是真的。

    我用两种不同的方法制作了两个按钮来测试它:

    <button onclick="window.location.href='/assets/hello.txt';">Download 1</button>
    
    <a href="/assets/hello.txt" download="my_file.txt"><button>Download 2</button></a>
    

    注意事项

    • 按钮 1 在新的浏览器选项卡中打开了文本文件。但是,按钮 1 下载无法自行打开的文件类型的文件(例如 .apk 文件)。
    • 按钮 2 下载了文本文件。但是,Button 2 仅在路径是相对路径时才下载文件。当我将路径更改为绝对路径时,浏览器会在新选项卡中打开它。

    我在 Firefox、Safari 和 Chrome 上对此进行了测试。

    【讨论】:

      【解决方案14】:

      这对我来说终于奏效了,因为要下载的文件是在页面加载时确定的。

      JS更新表单的action属性:

      function setFormAction() {
          document.getElementById("myDownloadButtonForm").action = //some code to get the filename;
      }
      

      调用JS更新表单的action属性:

      <body onLoad="setFormAction();">
      

      带有提交按钮的表单标签:

      <form method="get" id="myDownloadButtonForm" action="">
          Click to open document:  
          <button type="submit">Open Document</button>
      </form>
      

      以下操作没有起作用:

      <form method="get" id="myDownloadButtonForm" action="javascript:someFunctionToReturnFileName();">
      

      【讨论】:

      • 可能是因为如果您在加载时有文件,您不能使用模板引擎在服务器上呈现操作吗?为什么需要js代码?
      • 与此处使用默认表单操作的其他解决方案一样,这不一定会触发下载。它只是使浏览器导航到目标 URL。这是否导致该 URL 处的文件被下载或在浏览器中显示为页面取决于服务器在提供文件时返回的标头以及浏览器能够呈现的文件类型。
      【解决方案15】:

      在您的 &lt;body&gt;&lt;/body&gt; 标签之间的任何位置,使用以下代码放入一个按钮:

      <button>
          <a href="file.doc" download>Click to Download!</a>
      </button>
      

      这肯定行得通!

      【讨论】:

      • 对于 Chrome 来说这是一个很好的解决方案
      • 在 Safari 中也不起作用:W3 Schools
      • 不能在 MS 浏览器中运行是一个相当大的问题,Chrome 并不总是能解决问题。
      • 您不能在 HTML 中的按钮内放置链接
      • 不合法的 HTML; validator.w3.org/nu 抱怨 “元素 a 不能作为 button 元素的后代出现。” 似乎仍然在我尝试过的浏览器中呈现,但都是一样的,我不会冒险。
      【解决方案16】:

      如果您不能使用表单,downloadjs 的另一种方法很合适。 Downloadjs 在后台使用 blob 和 html 5 文件 API:

      <div onClick=(()=>{downloadjs(url, filename)})/>
      

      *它是jsx/react语法,但可以在纯html中使用

      【讨论】:

      • 为了避免其他域的图片出现 CORS 问题,请将 crossorigin="anonymous" 放入 img 标签中,如下所示:跨度>
      • 我有一个按钮,可以将内存中的字符串下载为文件。这行得通,没有问题。谢谢。
      【解决方案17】:

      &lt;a href="file.doc"&gt;&lt;button&gt;Download!&lt;/button&gt;&lt;/a&gt;
      这将下载文件,因为.doc文件扩展名不支持在浏览器中打开
      按钮和text-decoration 的最简单方法之一将有助于更改或删除链接的文本装饰。

      【讨论】:

      • 有史以来最简单的解决方案。
      【解决方案18】:

      不是真正的原始问题的答案,但它可能会帮助面临与我类似情况的其他人。

      如果您要下载的文件不在同一来源上,但您希望能够下载它,您可以使用Content-Disposition header 来实现。确保服务器在响应文件请求时包含标头。

      设置一个像 Content-Disposition: attachment 将确保文件将被下载而不是在浏览器中查看。

      在这种情况下,一个简单的&lt;a href="http://www.notMyOrigin.com/file.txt"&gt;Download&lt;/a&gt; 指向您的文件应该下载它。

      【讨论】:

        【解决方案19】:

        如果你愿意

        <a href="path_to_file" download="proposed_file_name">Download</a>
        

        用于下载将由浏览器呈现的文件的能力,但仍希望在按钮中使用简洁的 javascript 函数;您可以在 html 中有一个不可见的链接,然后在 javascript 中单击它。

        function download_file() {
          document.getElementById("my_download").click()
        }
        <a id="my_download" href="path_to_file" download="file_name" style="display:none;"></a>
        
        <button onClick="download_file()">Download!!!</button>

        【讨论】:

          【解决方案20】:

          如果您有一个复杂的 URL,例如 file.doc?foo=bar&amp;jon=doe,另一种方法是在表单中添加隐藏字段

          <form method="get" action="file.doc">
            <input type="hidden" name="foo" value="bar" />
            <input type="hidden" name="john" value="doe" />
            <button type="submit">Download Now</button>
          </form>
          

          受到@Cfreak 不完整答案的启发

          【讨论】:

            【解决方案21】:

            我想出的解决方案是你可以在锚标签中使用下载属性,但它只有在你的 html 文件在服务器上时才有效。但是你可能有一个问题,比如在设计一个简单的 html 页面时,我们如何检查你是否可以使用 VS code 实时服务器或括号实时服务器,你会看到你的下载属性可以工作,但如果你尝试简单地打开它只需双击 html 页面即可打开文件而不是下载文件。 结论:仅当您的 html 文件不是服务器时,锚标记中的属性下载才有效。

            【讨论】:

              【解决方案22】:

              对我来说,添加按钮而不是锚文本效果很好。

              <a href="file.doc"><button>Download!</button></a>
              

              按照大多数规则可能不太好,但看起来还不错。

              【讨论】:

              • 这仅适用于您的浏览器不支持 .doc 文件。
              • 您的 HTML 无效。 &lt;a&gt; 元素不能包含 &lt;button&gt; 元素。
              • 总是这样吗?当您发表评论时,这个答案已经两年了。
              【解决方案23】:

              如果您使用&lt;a&gt; 标签,请不要忘记使用指向该文件的整个 url -- 即:

              <a href="http://www.example.com/folder1/file.doc">Download</a>
              

              【讨论】:

              • 我认为这不是问题所在。如果链接与文件位于同一路径中,则也不需要“绝对”路径。
              • @Rocket - 当然,您对绝对路径是正确的,但是,这是确保正确的最佳方法。我会把它留给 OP 来决定它是否有帮助 -
              • 问题是明确询问如何使用按钮而不是链接来做到这一点。
              • 此解决方案中缺少下载属性。即使添加了下载属性,也无法跨域使用。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2021-10-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-12-09
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多