【问题标题】:Is there any way to specify a suggested filename when using data: URI?有没有办法在使用 data: URI 时指定建议的文件名?
【发布时间】:2010-09-21 23:43:03
【问题描述】:

例如,如果您点击链接:

data:application/octet-stream;base64,SGVsbG8=

浏览器将提示您下载一个文件,该文件包含超链接本身中以 base64 形式保存的数据。有没有办法在标记中建议默认名称?如果没有,是否有 JavaScript 解决方案?

【问题讨论】:

  • 可能与此问题无关,但如果这不是服务器或旧浏览器障碍,我建议使用 blob 的 & URL.createObjectURL
  • 部分浏览器支持mediatype的可选参数“name”:data:application/pdf;name=document.pdf;base64,BASE64_DATA_ENCODED
  • 我遇到了 Firefox pdf.js 的问题,如果它无法从数据 uri 中提取文件名,它在某些情况下往往会挂起。见stackoverflow.com/questions/45585921/…
  • @mems 哪些浏览器支持“name”参数?你能指点我一些参考文件吗? (我的 google-fu 让我失望了)。
  • @DimuDesigns 至少是当时的 Firefox。似乎不再是这种情况了。它与 MIME Con​​tent-Type (!= Content-Disposition) "name" 参数有关(不在 RFC 中?)

标签: javascript html url data-uri save-as


【解决方案1】:

使用download 属性:

<a download='FileName' href='your_url'>

The download attribute works on Chrome、Firefox、Edge、Opera、桌面版 Safari 10+、iOS Safari 13+,而不是 IE11。

【讨论】:

  • @BioDesign:它甚至适用于 chrome 中的 data:URI。见:jsfiddle.net/pYpqW
  • 但是你不能用window.location.replace来做。如果你例如想要创建一个 data:uri 或由window.URL.createObjectURL 生成的一个,并将其下载为文件,您必须创建一个 并单击它:jsfiddle.net/flyingsheep/wpQtH(不,$(...).click() 不起作用)
  • 只有在所有浏览器都像 Chrome 一样... [叹息]
  • @flyingsheep $('&lt;a href="data:text/plain,Test" download="test.txt"&gt;')[0].click() 似乎在这里工作正常(Chrome 23)(注意:我使用了原生的 click 方法,而不是 jQuery 的方法)。演示:jsfiddle.net/2zsRW
  • @flyingsheep 似乎他们正在 Firefox 中执行同源策略“在 Firefox 20 中,此属性仅适用于指向同源资源的链接。” developer.mozilla.org/en-US/docs/Web/HTML/Element/a 在我的测试中,Chrome 没有这个限制。
【解决方案2】:

如今,Chrome 让这一切变得非常简单:

function saveContent(fileContents, fileName)
{
    var link = document.createElement('a');
    link.download = fileName;
    link.href = 'data:,' + fileContents;
    link.click();
}

【讨论】:

  • 我知道所有这些其他答案都在谈论什么,这在 Chrome 30 中首次尝试。
  • 现在可以了,但并不总是那么容易。其中许多答案来自多年前。它们也适用于其他浏览器。
  • 浏览器兼容性的完整列表请参考http://caniuse.com/#feat=download
  • @tixastronauta:尽管该页面中有信息,但在我的 Firefox 44 中无法正常工作。在 Chrome 中运行良好。 48
  • 嗨@Holf 有没有办法添加文件类型或扩展名,或者就像文件名一样简单?
【解决方案3】:

仅 HTML: 使用 download 属性:

&lt;a download="logo.gif" href="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"&gt;Download transparent png&lt;/a&gt;

仅限Javascript:您可以使用此代码保存任何数据URI:

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

    //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 = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
saveAs(file, 'logo.gif');

Chrome、Firefox 和 Edge 13+ 将使用指定的文件名。

IE11、Edge 12 和 Safari 9don't support the download attribute)将使用默认名称下载文件或者他们只会在新标签中显示,如果它是受支持的文件类型:图像、视频、音频文件……

【讨论】:

  • 两个演示在 Chrome 38 中对我来说都可以正常工作(但它们应该在 Chrome 14+ 中工作)
  • 为了更完整的解决方案,我建议使用downloadjs on npm
  • 它适用于我,但之后浏览器页面会刷新。想知道如何防止这种情况发生?
  • 文件大小在 chrome 中不可用 > 2MB 由于 chrome stackoverflow.com/questions/695151/… 的限制
  • 限制属于data: URI,这就是问题提到的。这个答案也适用于 Blob 和其他任何有 URI 的东西
【解决方案4】:

根据RFC 2397,不,没有。

&lt;a&gt; 元素中似乎也没有任何attribute 可以使用。

然而 HTML5 随后在 &lt;a&gt; 元素上引入了 download 属性,尽管在撰写本文时支持并不普遍(例如,不支持 MSIE)

【讨论】:

  • 第二句话在撰写本文时是正确的,但 isn’t anymore。不过,到目前为止,它还没有被广泛实施。
  • this comment了解更多信息:)
  • @flyingsheep,它广泛实施。
  • 我写那条评论还不是三年前
  • 文件过长下载失败
【解决方案5】:

我在 netwerk/protocol/data/nsDataHandler.cpp 中查看了一些 firefox 源代码

数据处理程序仅解析内容/类型和字符集,并查看是否存在“;base64” 在字符串中

rfc 没有指定文件名,至少 firefox 没有为它处理文件名, 代码生成一个随机名称加上“.part”

我还检查了 firefox 日志

[b2e140]: DOCSHELL 6e5ae00 InternalLoad data:application/octet-stream;base64,SGVsbG8=
[b2e140]: Found extension '' (filename is '', handling attachment: 0)
[b2e140]: HelperAppService::DoContent: mime 'application/octet-stream', extension ''
[b2e140]: Getting mimeinfo from type 'application/octet-stream' ext ''
[b2e140]: Extension lookup on '' found: 0x0
[b2e140]: Ext. lookup for '' found 0x0
[b2e140]: OS gave back 0x43609a0 - found: 0
[b2e140]: Searched extras (by type), rv 0x80004005
[b2e140]: MIME Info Summary: Type 'application/octet-stream', Primary Ext ''
[b2e140]: Type/Ext lookup found 0x43609a0

如果您想查看 mozilla 源代码,可以查看有趣的文件:

data uri handler: netwerk/protocol/data/nsDataHandler.cpp
where mozilla decides the filename: uriloader/exthandler/nsExternalHelperAppService.cpp
InternalLoad string in the log: docshell/base/nsDocShell.cpp

我认为您现在可以停止搜索解决方案,因为我怀疑没有:)

正如在此线程中注意到的那样,html5 具有 download 属性,它也适用于 firefox 20 http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#attr-hyperlink-download

【讨论】:

  • 酷!虽然我不一定同意 Firefox 是存在的最终权威。 :)
【解决方案6】:

以下 Javascript sn-p 通过使用链接的新“下载”属性并模拟点击在 Chrome 中运行。

function downloadWithName(uri, name) {
  var link = document.createElement("a");
  link.download = name;
  link.href = uri;
  link.click();
}

下面的例子展示了它的用途:

downloadWithName("data:,Hello%2C%20World!", "helloWorld.txt")

【讨论】:

  • 这在 Firefox 中不起作用,我在下面添加了具有 Fx 兼容性的扩展答案。
【解决方案7】:

没有。

整个目的是它是一个数据流,而不是一个文件。数据源不应该知道用户代理将其作为文件处理......而且它没有。

【讨论】:

  • data: 的目的是将内部数据块捏造成URL格式,而无需从基于协议的源读取它. @silex 答案中的链接表明,即使尚未实现,建议首选名称write 的能力也被认为是有用的。
  • @Alnitak:有用吗?绝对地。技术上合适吗?还是不服气。 :)
  • @Tomalak 考虑加载数据和保存数据之间的区别——仅仅因为 blob 在数据中内联编码:URL 并不意味着它不应该有一个首选名称来保存它.
  • 但是你关于它的“全部目的”的说法是错误的。 data: 是专门为允许(小)inline 内容以一种捏造在一起的 URL 格式出现的,这样它就可以被诸如图像标签之类的东西使用,而无需单独的 HTTP 请求。 HTML 表示 img src 属性的内容必须是 URL,这就是 RFC 2397 创建的内容。没有“数据源”。
  • @Alnitak:没错。没有数据源。没有上下文。 URI 数据。
【解决方案8】:

您可以将下载属性添加到锚元素。

样本:

<a download="abcd.cer"
    href="data:application/stream;base64,MIIDhTC......">down</a>

【讨论】:

    【解决方案9】:

    使用service workers,这终于是真正意义上的可能了。

    1. 创建一个虚假的 URL。例如 /saveAs/myPrettyName.jpg
    2. &lt;a href, &lt;img src 中使用 URL,window.open( url ),绝对是可以使用“真实”URL 完成的任何事情。
    3. 在 Worker 内部,捕获 fetch 事件,并以正确的数据进行响应。

    浏览器现在会建议 myPrettyName.jpg,即使用户在新选项卡中打开文件并尝试将其保存在那里。就像文件来自服务器一样。

    // In the service worker
    self.addEventListener( 'fetch', function(e)
    {
        if( e.request.url.startsWith( '/blobUri/' ) )
        {
            // Logic to select correct dataUri, and return it as a Response
            e.respondWith( dataURLAsRequest );
        }
    });
    

    【讨论】:

    【解决方案10】:

    看看这个链接: http://lists.w3.org/Archives/Public/uri/2010Feb/0069.html

    引用:

    它甚至可以在末尾使用 ;base64 (如,不会导致问题)
    像这样(至少在 Opera 中):

    data:text/plain;charset=utf-8;headers=Content-Disposition%3A%20attachment%3B%20filename%3D%22with%20spaces.txt%22%0D%0AContent-Language%3A% 20en;base64,4oiaDQo%3D

    在讨论的其余消息中也有一些信息。

    【讨论】:

    • 很遗憾这没有下载。
    • 此讨论是针对数据 URI 格式的提议扩展 - 它尚未实现。
    • 实现与否,在现有对任意参数的支持下,这将是一个很好的选择。
    【解决方案11】:

    Google 代码上有一个对我有用的小变通脚本:

    http://code.google.com/p/download-data-uri/

    它添加一个包含数据的表单,提交它,然后再次删除该表单。哈基,但它为我完成了工作。需要 jQuery。

    此主题在 Google 代码页面之前出现在 Google 中,我认为将链接也放在此处可能会有所帮助。

    【讨论】:

    • 有趣的脚本,但它确实需要服务器获取响应并将其发回,对吗? jsfiddle.net/hZySf
    • 我不确定文件是从哪里生成的。该文件是否存储在 base64 编码中? (我对base64不太熟悉)
    • @streetlight:“文件”(即数据)由 Javascript 生成。该项目的上下文(可能是这里的大多数)假设您有某种方法可以将所需的数据放入 JS 变量中。不同之处在于,该脚本不是通过data:... URI 将其呈现给用户,而是创建一个表单以将其发布到服务器。然后服务器可能会直接将其作为 HTTP“下载”响应回显(即使用适当的 Content-Disposition 标头指定文件名)。
    【解决方案12】:

    这是一个基于 Holf 版本的 jQuery 版本,适用于 Chrome 和 Firefox,而他的版本似乎只适用于 Chrome。在身体上添加一些东西来做到这一点有点奇怪,但如果有人有更好的选择,我完全赞成。

    var exportFileName = "export-" + filename;
    $('<a></a>', {
        "download": exportFileName,
        "href": "data:," + JSON.stringify(exportData, null,5),
        "id": "exportDataID"
    }).appendTo("body")[0].click().remove();
    

    【讨论】:

    • 在 jQuery 1.11 中,由于 .remove() 而出现异常。我通过将$().appendTo() 分配给一个变量然后调用variable.click(); variable.remove() 来解决这个问题
    • @p0lar_bear 您应该使用任何 jQuery 获得该异常,因为从任何“jQuery 元素”获取 [0] 应该返回它所代表的第一个 DOM 元素,这实质上是“带你离开”jQuery。
    • 您实际上根本不需要附加/删除元素——请参阅stackoverflow.com/a/17311705/1037948的 cmets
    【解决方案13】:

    这个适用于 Firefox 43.0(旧版本未测试):

    dl.js:

    function download() {
      var msg="Hello world!";
      var blob = new File([msg], "hello.bin", {"type": "application/octet-stream"});
    
      var a = document.createElement("a");
      a.href = URL.createObjectURL(blob);
    
      window.location.href=a;
    }
    

    dl.html

    <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
    
    <head>
        <meta charset="utf-8"/>
        <title>Test</title>
        <script type="text/javascript" src="dl.js"></script>
    </head>
    
    <body>
    <button id="create" type="button" onclick="download();">Download</button>
    </body>
    </html>
    

    如果单击按钮,它会提供一个名为 hello.bin 的文件供下载。诀窍是使用 File 而不是 Blob

    参考:https://developer.mozilla.org/de/docs/Web/API/File

    【讨论】:

      【解决方案14】:

      (此答案已被新技术弃用,但出于历史兴趣将保留在这里。)

      这有点骇人听闻,但我以前也遇到过同样的情况。我在 javascript 中动态生成一个文本文件,并希望通过使用 data-URI 对其进行编码来提供它以供下载。

      这可以通过minor主要的用户干预来实现。生成链接&lt;a href="data:..."&gt;right-click me and select "Save Link As..." and save as "example.txt"&lt;/a&gt;。正如我所说,这很不优雅,但如果您不需要专业的解决方案,它就可以工作。

      首先使用 flash 将名称复制到剪贴板可以减轻这种痛苦。当然,如果您让自己使用 Flash 或 Java(我认为现在浏览器支持越来越少?),您可能会找到另一种方法。

      【讨论】:

      • 这不是解决方案,也不符合要求。对不起。
      • 大声笑@“次要用户干预”。让用户为你做所有事情并不是“轻微的用户干预”。
      • 将此与stackoverflow.com/questions/17311645/… 结合以触发生成的链接,您不需要用户干预。您可以指定HTML5 download attribute 来建议many other answers 提到的名称。
      • 这是 Safari 的一个很好的解决方法。使用 Modernizr 检测何时不支持下载属性并更新链接文本!
      【解决方案15】:

      &lt;a href=.. download=.. &gt; 适用于左键单击和右键单击-> 将链接另存为..,

      &lt;img src=.. download=.. &gt; 不适用于右键单击 -> 将图像另存为.. ,建议使用“Download.jped”。

      如果你将两者结合起来:&lt;a href=.. download=..&gt;&lt;img src=..&gt;&lt;/a&gt;

      它适用于左键单击,右键单击 -> 将链接另存为..,右键单击 -> 将图像另存为..

      你必须写两次 data-uri(href 和 src),所以对于大的图像文件,最好用 javascript 复制 uri。

      使用 Chrome/Edge 88 测试

      【讨论】:

        【解决方案16】:
        var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6
        var sessionId ='\n';
        var token = '\n';
        var caseId = CaseIDNumber + '\n';
        var url = casewebUrl+'\n';
        var uri = sessionId + token + caseId + url;//data in file
        var fileName = "file.i4cvf";// any file name with any extension
        if (isIE)
            {
                    var fileData = ['\ufeff' + uri];
                    var blobObject = new Blob(fileData);
                    window.navigator.msSaveOrOpenBlob(blobObject, fileName);
            }
            else //chrome
            {
                window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
                 window.requestFileSystem(window.TEMPORARY, 1024 * 1024, function (fs) {
                    fs.root.getFile(fileName, { create: true }, function (fileEntry) { 
                        fileEntry.createWriter(function (fileWriter) {
                            var fileData = ['\ufeff' + uri];
                            var blob = new Blob(fileData);
                            fileWriter.addEventListener("writeend", function () {
                                var fileUrl = fileEntry.toURL();
                                var link = document.createElement('a');
                                link.href = fileUrl;
                                link.download = fileName;
                                document.body.appendChild(link);
                                link.click();
                                document.body.removeChild(link);
                            }, false);
                            fileWriter.write(blob);
                        }, function () { });
                    }, function () { });
                 }, function () { });
            }
        

        【讨论】:

        【解决方案17】:

        您实际上可以在 Chrome 和 FireFox 中实现这一点。

        试试下面的网址,它会下载使用过的代码。

        data:text/html;base64,PGEgaHJlZj0iZGF0YTp0ZXh0L2h0bWw7YmFzZTY0LFBHRWdhSEpsWmowaVVGVlVYMFJCVkVGZlZWSkpYMGhGVWtVaUlHUnZkMjVzYjJGa1BTSjBaWE4wTG1oMGJXd2lQZ284YzJOeWFYQjBQZ3BrYjJOMWJXVnVkQzV4ZFdWeWVWTmxiR1ZqZEc5eUtDZGhKeWt1WTJ4cFkyc29LVHNLUEM5elkzSnBjSFErIiBkb3dubG9hZD0idGVzdC5odG1sIj4KPHNjcmlwdD4KZG9jdW1lbnQucXVlcnlTZWxlY3RvcignYScpLmNsaWNrKCk7Cjwvc2NyaXB0Pg==
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-11-09
          • 2021-01-28
          相关资源
          最近更新 更多