【问题标题】:how to set content-disposition = attachment via javascript?如何通过 javascript 设置 content-disposition = attachment?
【发布时间】:2011-04-27 21:36:53
【问题描述】:

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

基本上,我想在页面通过 Javascript 加载后,使用 Firefox 强制执行“SaveAs”操作。

我该怎么做?

【问题讨论】:

    标签: javascript html http-headers


    【解决方案1】:

    1.使用Anchor“下载”(HTML5)属性

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

    2.使用js以编程方式创建href,

    const link = document.createElement('a');
    link.href = '/xyz/abc.pdf';
    link.download = "file.pdf";
    link.dispatchEvent(new MouseEvent('click'));
    

    根据 Mozilla doc Anchor element,下载属性 (HTML5) 指示浏览器下载 URL 而不是导航到它。

    重要提示:

    • 此属性仅适用于同源 URL。
    • 虽然 HTTP(s) URL 需要同源,但允许使用 blob: URL 和 data: URL,以便可以下载由 JavaScript 生成的内容,例如在图像编辑器 Web 应用程序中创建的图片。

    所以上述动态创建锚元素并使用它下载文件的js方法仅适用于相同的源文件,即 有两种方法可以处理这个问题 ->

    • 客户端
    • 服务器端

    客户端解决方案:->

    解决此问题的方法,在第二个注释中引用,即可以在 fetch js API 的帮助下使用 blob 对象

    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 响应标头是一个标头,指示内容是否希望在浏览器中内联显示,即作为网页或网页的一部分,或作为附件,即下载并保存在本地。 例如

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

    对于托管在 AWS 上的文件,可以编辑其响应标头,可以在元数据中更改这些标头,在文件或文件夹属性的元数据中添加内容处置标头,添加键作为内容处置和值作为附件,

    content-disposition : attachment
    

    现在,每当从浏览器中点击此文件时,它总是会下载而不是打开,现在如果您在锚标记中使用此文件链接,它将使用下载 html 标记直接下载。

    【讨论】:

    • 我在aws中添加了content-disposition,但是chrome仍然在PDF查看器中打开它,而不是提示保存文件。我还能做些什么来防止 chrome 自动打开它?
    • 编辑:一段时间后,我可以得到另存为提示。也许 AWS 延迟了元数据更改的影响。谢谢!
    • 您是如何获得另存为提示的,chrome 只是使用密钥从 aws 下载文件?当 url 过期时会发生什么,它会将您带到 403 错误页面,我想知道如何处理
    【解决方案2】:

    基于 Firefox 和 Chromium 的浏览器支持 download attribute。如果您现在需要更好的兼容性,请使用基于 Flash 的 Downloadify 作为后备。


    仅 HTML: 使用 download 属性:

    &lt;a download href="http://upload.wikimedia.org/wikipedia/commons/b/bb/Wikipedia_wordmark.svg"&gt;Download&lt;/a&gt;

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

    【讨论】:

    • 当我尝试这个(作为一个完整的 javaScript 新手)时,它的行为就像我使用了“true”作为下载文件的所需名称。我认为它需要是link.setAttribute('download',''); 以避免为下载文件提供建议的名称?
    • 自 2018 年春季起,此方法不再适用于跨域请求:developer.mozilla.org/en-US/docs/Web/HTML/Element/a#Attributes
    • 哇,真是可悲。因此,在这种情况下,唯一的选择是在服务器上使用 Content-Disposition 标头。
    • +1 好消息:“如果 [download] 属性有值,则将其用作保存提示中的预填充文件名(用户仍然可以根据需要更改文件名).” 坏消息:“如果 HTTP 标头 Content-Disposition: 给出的文件名与此属性不同,则 HTTP 标头优先于此属性。”
    【解决方案3】:

    Content-Disposition 是response header,即。服务器必须返回它。您无法使用客户端 javascript 实现此目的。

    【讨论】:

    • 没错,我就是这么想的。
    猜你喜欢
    • 2022-01-20
    • 2015-03-11
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-08
    相关资源
    最近更新 更多