如何通过JavaScript设置content-disposition = attachment?

19

如何通过JavaScript设置content-disposition = attachment

基本上,我想在页面加载后通过JavaScript使用Firefox强制执行"另存为"操作。

我该如何做到这一点?

3个回答

30

Content-Disposition是一个响应头,即服务器必须返回它。您无法使用客户端JavaScript实现此功能。


没错,这就是我想的。 - Prakash Raman

16

仅限HTML:使用download属性

<a download href="http://upload.wikimedia.org/wikipedia/commons/b/bb/Wikipedia_wordmark.svg">Download</a>


仅使用JavaScript:您可以使用此代码保存任何文件:

function saveAs(uri) {
    var link = document.createElement('a');
    if (typeof link.download === 'string') {
        link.href = uri;
        link.setAttribute('download', true);

        //Firefox requires the link to be in the body
        document.body.appendChild(link);

        //simulate click
        link.click();

        //remove the link when done
        document.body.removeChild(link);
    } else {
        window.open(uri);
    }
}

var file = 'http://upload.wikimedia.org/wikipedia/commons/b/bb/Wikipedia_wordmark.svg';
saveAs(file);


1
当我尝试这个(作为一个完全的JavaScript新手)时,它的行为就像我已经使用了“true”作为所需下载文件的名称。我认为需要link.setAttribute('download','');来避免提供下载文件的建议名称? - Speed8ump
1
截至2018年春季,这种方法不再适用于跨域请求:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#Attributes - theMaestro73
哇,那真是太遗憾了。因此,在这种情况下,唯一的选择是在服务器上使用“Content-Disposition”头文件。 - fregante
2
好消息:如果[download]属性有值,它将作为保存提示中预填充的文件名(用户仍然可以更改文件名,如果他们想要的话)。坏消息:如果HTTP头Content-Disposition:给出的文件名与此属性不同,则HTTP头优先于此属性。 - Nate Anderson

5

1.使用HTML5中的锚点"download"属性

<a href='abc.pdf' download>Click Here</a>

用js编写程序创建href链接
const link = document.createElement('a');
link.href = '/xyz/abc.pdf';
link.download = "file.pdf";
link.dispatchEvent(new MouseEvent('click'));

根据Mozilla文档锚元素,download属性(HTML5)指示浏览器下载URL而不是导航到它。
重要提示:
  • 此属性仅适用于同源的URL。
  • 虽然HTTP(s) URL需要在相同的源中,但允许使用blob: URL和data: URL,以便可以下载由JavaScript生成的内容,例如在图像编辑器Web应用程序中创建的图片。
因此,上述JS方法动态创建锚元素并使用它下载文件仅适用于同一来源文件,即存在两种处理此问题的方法->
  • 客户端
  • 服务器端
客户端解决方案:- >

为了解决这个问题,可以使用第二个注释中引用的blob对象,并借助fetch js API。

url = 'https://aws.something/abc.pdf';

fetch(url, {
      method: 'GET',
    }).then(function(resp) {
      return resp.blob();
    }).then(function(blob) {
      const newBlob = new Blob([blob], { type: "application/pdf", charset: "UTF-8" })

      // IE doesn't allow using a blob object directly as link href
      // instead it is necessary to use msSaveOrOpenBlob
      if (window.navigator && window.navigator.msSaveOrOpenBlob) {
        window.navigator.msSaveOrOpenBlob(newBlob);
        return;
      }
      const data = window.URL.createObjectURL(newBlob);
      const link = document.createElement('a');
      link.dataType = "json";
      link.href = data;
      link.download = "file.pdf";
      link.dispatchEvent(new MouseEvent('click'));
      setTimeout(function () {
        // For Firefox it is necessary to delay revoking the ObjectURL
        window.URL.revokeObjectURL(data), 60
      });
    });

服务器端解决方案:->

另一个选择是,如果您可以控制服务器端响应头,则这可能是最佳选择。

在常规的HTTP响应中,Content-Disposition 响应头是一个指示内容是否预期在浏览器中内联显示(即作为Web页面或Web页面的一部分),或作为附件下载并保存在本地的头部。 例如:

Content-Disposition: attachment
Content-Disposition: attachment; filename="filename.jpg"

在 AWS 托管的文件中,可以编辑其响应头。这些可以在元数据中进行更改,在文件或文件夹属性的元数据中添加内容处置标头,将键添加为 content-disposition,值添加为 attachment。
content-disposition : attachment

现在,每当从浏览器访问此文件时,它都会始终下载而不是打开。如果您在锚标签中使用此文件链接,则可以通过使用下载HTML标签直接下载。

我在AWS中添加了 content-disposition,但Chrome仍然会在PDF浏览器中打开它,而不是提示保存文件。除此之外,我还能做些什么来防止Chrome自动打开它吗? - zhuhang.jasper
经过一段时间的等待,我终于能够得到“另存为”提示了。可能是AWS延迟了元数据更改的影响。谢谢! - zhuhang.jasper
你是怎么得到“另存为”提示的?Chrome只是通过密钥从AWS下载文件。当URL过期时会发生什么?它会带你到一个403错误页面,我想知道如何处理这个问题。 - Ricky-U

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