我最近一直在摆弄WebGL,并得到了一个Collada阅读器工作。问题是它非常慢(Collada是一种非常冗长的格式),所以我将开始将文件转换为更容易使用的格式(可能是JSON)。我已经有代码来解析JavaScript文件,所以我不妨使用它作为我的出口商太!问题在于储蓄。

现在,我知道我可以解析文件,将结果发送到服务器,并让浏览器从服务器请求返回文件作为下载。但实际上,服务器与这个特定的进程没有任何关系,那么为什么要把它牵扯进来呢?我在内存中已经有了所需文件的内容。是否有任何方法可以使用纯JavaScript向用户提供下载?(我对此表示怀疑,但不妨问问……)

需要明确的是:我不会在用户不知情的情况下访问文件系统!用户将提供一个文件(可能通过拖放),脚本将转换内存中的文件,并提示用户下载结果。就浏览器而言,所有这些都应该是“安全”的活动。

[编辑]:我没有在前面提到它,所以那些回答“Flash”的帖子是有道理的,但我所做的部分工作是试图强调纯HTML5可以做什么……所以闪电侠正好适合我。(尽管这对于任何制作“真正的”web应用程序的人来说都是一个非常有效的答案)在这种情况下,除非我想要涉及服务器,否则我看起来很不走运。谢谢!


当前回答

function download(content, filename, contentType)
{
    if(!contentType) contentType = 'application/octet-stream';
        var a = document.createElement('a');
        var blob = new Blob([content], {'type':contentType});
        a.href = window.URL.createObjectURL(blob);
        a.download = filename;
        a.click();
}

其他回答

看看Doug Neiner的downadify,这是一个基于Flash的JavaScript界面。

downloadadify是一个很小的JavaScript + Flash库,可以在浏览器中生成和保存文件,而不需要服务器交互。

我发现了两种简单的方法。首先,使用已单击的元素并注入下载数据。其次,使用下载数据生成一个a元素,执行a.click()并再次删除它。但是第二种方法只有在用户点击操作调用时才有效。(一些)浏览器阻塞点击()从其他上下文,如加载或触发超时(setTimeout)。

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="UTF-8">
    <script type="text/javascript">
      function linkDownload(a, filename, content) {
        contentType =  'data:application/octet-stream,';
        uriContent = contentType + encodeURIComponent(content);
        a.setAttribute('href', uriContent);
        a.setAttribute('download', filename);
      }
      function download(filename, content) {
        var a = document.createElement('a');
        linkDownload(a, filename, content);
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
      }
    </script>
   </head>
  <body>
    <a href="#" onclick="linkDownload(this, 'test.txt', 'Hello World!');">download</a>
    <button onclick="download('test.txt', 'Hello World!');">download</button>
  </body>
</html>

HTML5定义了一个窗口。saveAs(blob, filename)方法。目前任何浏览器都不支持它。但是,有一个名为filesver .js的兼容性库将此功能添加到大多数现代浏览器(包括Internet Explorer 10+)。Internet Explorer 10支持导航器。msSaveBlob(blob, filename)方法(MSDN),在filesver .js中用于Internet Explorer支持。

我写了一篇关于这个问题的详细博文。

保存大文件

Long data URIs can give performance problems in browsers. Another option to save client-side generated files, is to put their contents in a Blob (or File) object and create a download link using URL.createObjectURL(blob). This returns an URL that can be used to retrieve the contents of the blob. The blob is stored inside the browser until either URL.revokeObjectURL() is called on the URL or the document that created it is closed. Most web browsers have support for object URLs, Opera Mini is the only one that does not support them.

强制下载

If the data is text or an image, the browser can open the file, instead of saving it to disk. To cause the file to be downloaded upon clicking the link, you can use the the download attribute. However, not all web browsers have support for the download attribute. Another option is to use application/octet-stream as the file's mime-type, but this causes the file to be presented as a binary blob which is especially user-unfriendly if you don't or can't specify a filename. See also 'Force to open "Save As..." popup open at text link click for pdf in HTML'.

指定文件名

如果blob是用File构造函数创建的,你也可以设置一个文件名,但只有少数web浏览器(包括Chrome和Firefox)支持File构造函数。文件名也可以指定为download属性的参数,但这需要考虑大量的安全问题。Internet Explorer 10和11提供了自己的方法msSaveBlob来指定文件名。

示例代码

var file; var data = []; data.push("This is a test\n"); data.push("Of creating a file\n"); data.push("In a browser\n"); var properties = {type: 'text/plain'}; // Specify the file's mime-type. try { // Specify the filename using the File constructor, but ... file = new File(data, "file.txt", properties); } catch (e) { // ... fall back to the Blob constructor if that isn't supported. file = new Blob(data, properties); } var url = URL.createObjectURL(file); document.getElementById('link').href = url; <a id="link" target="_blank" download="file.txt">Download</a>

try

let a = document.createElement('a'); a.href = "data:application/octet-stream,"+encodeURIComponent('我的数据'); a.download = 'myFile.json'; a.click ();//我们不添加'a'到DOM,所以不需要删除

如果你想下载二进制数据,看这里

更新

2020.06.14我将Chrome升级到83.0及以上SO代码片段停止工作(由于沙箱安全限制)-但JSFiddle版本工作-在这里