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

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

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

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


当前回答

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版本工作-在这里

其他回答

保存大文件

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>

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();
}

你可以用它来保存文本和其他数据:

function downloadFile(name, data) {
    let a = document.createElement("a");
    if (typeof a.download !== "undefined") a.download = name;
    a.href = URL.createObjectURL(new Blob([data], {
        type: "application/octet-stream"
    }));
    a.dispatchEvent(new MouseEvent("click"));
}

这个函数将创建一个Anchor元素,通过.download(如果支持的话)设置名称,分配一个从对象(url . createobjecturl)创建的url (.href),在本例中是一个Blob对象,并分派一个单击事件。简而言之:就好像你在点击一个下载链接。

示例代码

downloadFile("textfile.txt", "A simple text file");
downloadFile(
    "circle.svg",
    `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
        <circle cx="50" cy="50" r="42" />
    </svg>`
);
downloadFile(
    "utf8string.txt",
    new Uint8Array([85, 84, 70, 45, 56, 32, 115, 116, 114, 105, 110, 103]) // "UTF-8 string"
);

这个函数也接受File, Blob和MediaSource:

function downloadFile(name, data) {
    if (!(data instanceof File || data instanceof Blob || data instanceof MediaSource)) {
        return downloadFile(name, new Blob([data], {
            type: "application/octet-stream"
        }));
    }

    let a = document.createElement("a");
    if (typeof a.download !== "undefined") a.download = name;
    a.href = URL.createObjectURL(data);
    a.dispatchEvent(new MouseEvent("click"));
}

或者你可以使用两个函数:

function downloadFile(name, data) {
    return downloadObject(new Blob([data], {
        type: "application/octet-stream"
    }));
}

function downloadObject(name, object) {
    let a = document.createElement("a");
    if (typeof a.download !== "undefined") a.download = name;
    a.href = URL.createObjectURL(object);
    a.dispatchEvent(new MouseEvent("click"));
}

这个线程对于如何生成二进制文件并提示下载已命名的文件非常有价值,所有这些都在客户机代码中,没有服务器。

我的第一步是从我保存的数据中生成二进制blob。对于单个二进制类型有很多示例,在我的例子中,我有一个具有多个类型的二进制格式,您可以将其作为数组传递来创建blob。

saveAnimation: function() {

    var device = this.Device;
    var maxRow = ChromaAnimation.getMaxRow(device);
    var maxColumn = ChromaAnimation.getMaxColumn(device);
    var frames = this.Frames;
    var frameCount = frames.length;

    var writeArrays = [];


    var writeArray = new Uint32Array(1);
    var version = 1;
    writeArray[0] = version;
    writeArrays.push(writeArray.buffer);
    //console.log('version:', version);


    var writeArray = new Uint8Array(1);
    var deviceType = this.DeviceType;
    writeArray[0] = deviceType;
    writeArrays.push(writeArray.buffer);
    //console.log('deviceType:', deviceType);


    var writeArray = new Uint8Array(1);
    writeArray[0] = device;
    writeArrays.push(writeArray.buffer);
    //console.log('device:', device);


    var writeArray = new Uint32Array(1);
    writeArray[0] = frameCount;
    writeArrays.push(writeArray.buffer);
    //console.log('frameCount:', frameCount);

    for (var index = 0; index < frameCount; ++index) {

      var frame = frames[index];

      var writeArray = new Float32Array(1);
      var duration = frame.Duration;
      if (duration < 0.033) {
        duration = 0.033;
      }
      writeArray[0] = duration;
      writeArrays.push(writeArray.buffer);

      //console.log('Frame', index, 'duration', duration);

      var writeArray = new Uint32Array(maxRow * maxColumn);
      for (var i = 0; i < maxRow; ++i) {
        for (var j = 0; j < maxColumn; ++j) {
          var color = frame.Colors[i][j];
          writeArray[i * maxColumn + j] = color;
        }
      }
      writeArrays.push(writeArray.buffer);
    }

    var blob = new Blob(writeArrays, {type: 'application/octet-stream'});

    return blob;
}

下一步是让浏览器提示用户使用预定义的名称下载这个blob。

我所需要的只是在HTML5中添加一个命名链接,我可以重用它来重命名初始文件名。我把它隐藏起来,因为这个链接不需要显示。

<a id="lnkDownload" style="display: none" download="client.chroma" href="" target="_blank"></a>

最后一步是提示用户下载文件。

var data = animation.saveAnimation();
var uriContent = URL.createObjectURL(data);
var lnkDownload = document.getElementById('lnkDownload');
lnkDownload.download = 'theDefaultFileName.extension';
lnkDownload.href = uriContent;
lnkDownload.click();

您可以使用localStorage。这相当于Html5中的cookie。它似乎可以在Chrome和Firefox上运行,但在Firefox上,我需要将它上传到服务器上。也就是说,直接在我的家用电脑上测试不起作用。

我正在做HTML5的例子。访问http://faculty.purchase.edu/jeanine.meyer/html5/html5explain.html 转到迷宫一。重建迷宫的信息使用localStorage存储。

我读这篇文章是为了寻找用于加载和处理xml文件的HTML5 JavaScript。它是否与旧的html和JavaScript相同????