ChatGPT解决这个技术问题 Extra ChatGPT

单击 HTML 按钮或 JavaScript 时如何触发文件下载

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

我想要一个简单的文件下载,它会做同样的事情:

<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 结构(就像您接受的那个)的答案,为什么不也将锚定样式设置为按钮?我无法想象前两个会很好但作为按钮的锚会出现问题的场景。

M
MultiplyByZer0

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

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

在哪里:

path_to_file 是解析为同一来源的 URL 的路径。这意味着页面和文件必须共享相同的域、子域、协议(HTTP 与 HTTPS)和端口(如果指定)。例外是 blob: 和 data: (始终有效)和 file: (永远无效)。

提议的文件名是要保存到的文件名。如果为空,浏览器默认使用文件名。

文档:MDNHTML Standard on downloadingHTML Standard on downloadCanIUse


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

对于按钮你可以做

<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 时返回的标头以及浏览器能够呈现的文件类型。
A
Ani Menon

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 时返回的标头以及浏览器能够呈现的文件类型。
s
syntagma

一个简单的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)幸运的是没有,因为它在浏览器级别
这是最好的解决方案,应该被接受。
M
Mark Amery

使用 jQuery:

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

很好,谢谢。您是否知道大多数服务器是否会默认将 Content-Disposition 设置为“附件”?
没有“最”。这完全取决于。不要依赖它被设置。
这个问题一直在驱使我,这是唯一可行的选择(并且受 IE 支持)。我将为像我这样的任何 n00bs 添加设置 Content-Disposition,您所要做的就是:
没有jQuery。时期。
如果您尝试下载图像,这不起作用,它会在浏览器中打开图像
D
Danubian Sailor

您可以使用不可见 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 中工作。
从版本 61.0.3163.100(官方版本)(64 位)起可在 Chrome 中使用
不适用于 Firefox v57 中的图像。它只是在 iframe 中渲染图像。
但是,如果文件属于浏览器知道如何呈现自己的类型,这将静默失败(除非服务器返回一个 Content-Disposition 标头指示应下载文件)。
g
georgeawg

引导版本

<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 的强大功能。
问题是明确询问如何使用按钮而不是链接来执行此操作。
如果您对引导程序一无所知,您会发现它是一个按钮。
按钮标签对我不起作用。但是这个做到了。
D
Delconis

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

<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);
}

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

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

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

为了在 Firefox 中工作,资源必须与文档在同一个域中。设置 CORS 标头没有帮助。
永远不要这样做
J
John Weisz

关于什么:

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

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

您好,我只包含“下载”一词并且效果很好。

<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);

未捕获的 ReferenceError:未定义浏览器
D
David Willhite

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

常量下载 = document.getElementById("fileRequest"); download.addEventListener('click', request);函数请求() { window.location = 'document.docx'; } .dwnld-cta { 边界半径:15px 15px;宽度:100px; line-height: 22px }

下载文件


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

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

<a href="/assets/hello.txt" download="my_file.txt"><button>Download 2</button></a>

/assets/hello.txt 只是我网站上的相对路径。将其更改为您自己的相对路径。

my_file.txt 是您希望文件在下载时被调用的名称。

解释

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

我制作了两个按钮来使用两种不同的方法对其进行测试:

https://i.stack.imgur.com/1lmuI.png

<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 下载了文本文件。但是,按钮 2 仅在路径是相对路径时才下载文件。当我将路径更改为绝对路径时,浏览器会在新选项卡中打开它。

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


J
John Weisz

<body></body> 标记之间的任何位置,使用以下代码放入一个按钮:

<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 元素的后代出现。” 似乎仍然在我尝试过的浏览器中呈现,但同样,我不会冒险的。
s
slayernoah

这最终对我有用,因为要下载的文件是在加载页面时确定的。

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 处的文件被下载或显示为浏览器中的页面取决于服务器在提供文件时返回的标头以及浏览器能够呈现的文件类型。
M
Mark Amery

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

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

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


为了避免其他域上的图像出现 CORS 问题,请将 crossorigin="anonymous" 放入 img 标签中,如下所示:
我有一个按钮,可以将内存中的字符串下载为文件。这行得通,没有问题。谢谢。
m
m24197

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


有史以来最简单的解决方案。
S
Sebi Nechita

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

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

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

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


R
RKM

如果你想

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

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

function download_file() { document.getElementById("my_download").click() }


M
Mostafa Ghorbani

您需要做的就是在您输入的文件名之后添加下载:

前:

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

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

确保下载用大写字母书写,否则将无法正常工作。


B
BananaAcid

如果您有一个复杂的 URL(例如 file.doc?foo=bar&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 不完整的答案


s
sourabh sharma

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


B
Brana

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

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

大多数规则可能不太好,但它看起来相当不错。


这仅适用于您的浏览器不支持 .doc 文件。
您的 HTML 无效。 <a> 元素可能不包含 <button> 元素。
总是这样吗?当您发表评论时,这个答案已经两年了。
J
John Weisz

如果您使用 <a> 标记,请不要忘记使用指向该文件的整个 url - 即:

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

我不认为这是这里的问题。如果链接与文件位于同一路径中,则也不需要“绝对”路径。
@Rocket-当然,您对绝对路径是正确的,但是,这是确保正确的最佳方法。我会把它留给 OP 来决定它是否有帮助 -
问题是明确询问如何使用按钮而不是链接来执行此操作。
此解决方案中缺少下载属性。即使添加了下载属性,它也不适用于跨域。