如何在不使用带有下载属性的<a>元素或服务器的情况下下载文件?

13

2
你可以在这里检查我的答案:https://dev59.com/iVkT5IYBdhLWcg3wfvin#38552959 它能准确提供你所需要的。 - Dekel
你是在寻找2016浏览器兼容或者2017的解决方案吗? :) - Dekel
没有“服务器”是什么意思? - Dehan
文件的内容将会是什么?如果您能陈述整个故事会更好!同时,您可以尝试使用https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL。 - Dehan
@jdc91 请看_"最好能说清整个故事!"_ 请参考 https://stackoverflow.com/questions/38193605/how-to-updoad-in-old-browsers-ex-safari-5-1-4, https://dev59.com/RVoT5IYBdhLWcg3wxxsk/ - guest271314
显示剩余3条评论
6个回答

18

有几种方法可以触发下载。以下是其中之一:

使用表单:

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

使用JavaScript:

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

如果用户有打开mydoc.doc的浏览器插件,那么它会如何下载? - Abdur Rehman
用户可以通过浏览器插件选择保存他们看到的内容。但是,你不能强制从前端下载。请参见:https://stackoverflow.com/questions/8613725/how-can-i-force-download-with-html-and-or-javascript/8613899#8613899 - Leo Farmer
window.open("blob:xyz") 在2023年对我来说仍然运行良好。这是参考链接:https://developer.mozilla.org/en-US/docs/Web/API/Window/open - Justin

3
尽管我支持@LeoFarmer的答案,但我还想提供两种“可黑客化”的方法:
  1. 如果文件非常小,则可以使用带有href='data:[<mediatype>][;base64],<data>'a 标签。

    这样可以在 mediatype 中添加内容并模拟 HTTP 头。这个黑客技术可能并不像人们所期望的那么通用。

  2. 对于小到中等大小的文件,可以使用 AJAX 下载文件,然后使用 Javascript 文件 API 提示用户保存文件(API 不支持保存,但很容易将数据转换为数据 URL)。

    如果你想避免使用 Javascript 文件 API,可以尝试模拟锚点点击,就像这里建议的那样

再次提醒,正如 @Leo Farmer 指出的那样,这些解决方案不能保证浏览器不会将文件打开到新标签页而不是保存到磁盘,但我认为所有用户都能够优雅地降级到 cmd+Sctrl+S 键盘快捷键 :-)

3

使用FileSaver.js

它支持所有常用的浏览器。

只需包含以下内容:

<script type="text/javascript" src="FileSaver.min.js"></script>

并且像这样使用:

var file = new File(["Hello, world!"], "hello world.txt", {type: "text/plain;charset=utf-8"});
saveAs(file);

注意: 为了使它在Safari < 6,Opera < 15和FireFox < 20中也能正常工作,您需要将Blob.js作为依赖项包含进来。


在回答的最后一句提到的浏览器中,File 构造函数是否可用? - guest271314
不,他们不支持。但是请查看FileSaver.js的文档,那里有其他保存方式。希望对您有所帮助。 :) - padr
太棒了!它简直就是完美的,即使在使用TypeScript的情况下,也是在主流浏览器中最简单的方法。我将"file-saver"添加到"types" tsconfig选项中,并在项目的任何地方使用"saveAs"作为一个方法(需要在使用它在TypeScript模块内部时忽略错误)。用于分发的压缩版本在这里 - undefined

2
您可以使用download属性和jQuery来实现此操作。但是,download属性不支持IE和Safari / iOS。因此,您可以使用jQuery来完成这个功能。
 $('.download').click(function(e) {
    e.preventDefault();  //stop the browser from following
    window.location.href = 'uploads/file.doc';
});

<a href="no-script.html" class="download">Download</a>

1
你可以使用 数据 URI data:[<mediatype>][;base64],<data> 文件表示,无论是手动创建还是利用 FileReader().readAsDataURL(),并将 MIME 类型设置为 application/octet-stream,使用 encodeURIComponent()window.open()
<script>
  var file = "data:application/octet-stream,"
             + encodeURIComponent("<!DOCTYPE html>"
             + "<html><body>"
             + "<div>abc</div>"
             + "</body></html>");
  var saveFile = window.open(file, "_self");     
</script>

<script>
  var blob = new Blob(["abc"], {type:"text/plain"});
  var reader = new FileReader();
  reader.addEventListener("load", function(e) {
    // replace existing `MIME` type with `application/octet-stream`
    var file = "data:application/octet-stream;" 
                + e.target.result.split(/;/)[1];
    var saveFile = window.open(file, "_self");
  });
  reader.readAsDataURL(blob)
</script>

plnkr http://plnkr.co/edit/IS1OC0laRwL3BuuF9zay?p=preview

可能是一个与编程有关的链接或代码片段。

-1

如果您正在使用服务器端,则请遵循表单提交机制来呈现页面。在MVC中,我们可以使用以下代码

Html

  @using (Html.BeginForm("GetAttachment", "User", FormMethod.Post))
                {

                    <button type="submit">Download</button>   
                }

MVC 控制器

public ActionResult GetAttachment()
{
   string filename = "File.pdf";
string filepath = AppDomain.CurrentDomain.BaseDirectory + "/Path/To/File/" + filename;
byte[] filedata = System.IO.File.ReadAllBytes(filepath);
string contentType = MimeMapping.GetMimeMapping(filepath);

var cd = new System.Net.Mime.ContentDisposition
{
    FileName = filename,
    Inline = true,
};

Response.AppendHeader("Content-Disposition", cd.ToString());

return File(filedata, contentType);
}

使用表单将数据提交到服务器,服务器返回文件。 - Pradeep Kumar Das
1
一个 <form> 不需要被提交到服务器。问题的要求是不使用服务器。 - guest271314
我可以使用 $.fileDownload('/url/to/download.pdf'); 属性吗? - Pradeep Kumar Das
1
不确定您的意思是什么? - guest271314
1
为什么需要一个jQuery插件? - guest271314
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接