首页 文章

在内存中创建一个文件供用户下载,而不是通过服务器

提问于
浏览
676

有没有办法在客户端创建文本文件并提示用户下载它,而不与服务器进行任何交互?我知道我不能直接写入他们的机器(安全和所有),但是我可以创建并提示他们保存它吗?

17 回答

  • 370

    您甚至可以做一个比URI更好的方法 - 使用Chrome,您还可以建议文件的名称,如this blog post about naming a download when using URIs中所述 .

  • 154

    以上所有示例在chrome和IE中都运行良好,但在Firefox中失败 . 请考虑在身体上添加锚点并在点击后将其移除 .

    var a = window.document.createElement('a');
    a.href = window.URL.createObjectURL(new Blob(['Test,Text'], {type: 'text/csv'}));
    a.download = 'test.csv';
    
    // Append anchor to body.
    document.body.appendChild(a);
    a.click();
    
    // Remove anchor from body
    document.body.removeChild(a);
    
  • 569

    根据@Rick的答案,这真的很有帮助 .

    如果你想以这种方式分享它,你必须scape字符串 data

    $('a.download').attr('href', 'data:application/csv;charset=utf-8,'+ encodeURI(data));
    

    “抱歉,由于我目前在StackOverflow中的声誉很低,我无法对@ Rick的答案发表评论 .

    edit suggestion被分享并被拒绝 .

  • -19

    以上所有解决方案都不适用于所有浏览器 . 以下是最终适用于IE 10,Firefox和Chrome(以及 without jQuery或任何其他库)的内容:

    save: function(filename, data) {
        var blob = new Blob([data], {type: 'text/csv'});
        if(window.navigator.msSaveOrOpenBlob) {
            window.navigator.msSaveBlob(blob, filename);
        }
        else{
            var elem = window.document.createElement('a');
            elem.href = window.URL.createObjectURL(blob);
            elem.download = filename;        
            document.body.appendChild(elem);
            elem.click();        
            document.body.removeChild(elem);
        }
    }
    

    请注意,根据您的具体情况,您可能还需要在删除 elem 后调用URL.revokeObjectURL . 根据URL.createObjectURL的文档:

    每次调用createObjectURL()时,即使您已经为同一个对象创建了一个对象URL,也会创建一个新的对象URL . 必须通过在不再需要时调用URL.revokeObjectURL()来释放其中的每一个 . 浏览器将在卸载文档时自动释放这些内容;但是,为了获得最佳性能和内存使用,如果有明确卸载它们的安全时间,则应该这样做 .

  • 21

    您可以使用数据URI . 浏览器支持不同;见Wikipedia . 例:

    <a href="data:application/octet-stream;charset=utf-16le;base64,//5mAG8AbwAgAGIAYQByAAoA">text file</a>
    

    八位字节流是强制下载提示 . 否则,它可能会在浏览器中打开 .

    对于CSV,您可以使用:

    <a href="data:application/octet-stream,field1%2Cfield2%0Afoo%2Cbar%0Agoo%2Cgai%0A">CSV Octet</a>
    

    试试jsFiddle demo .

  • 9

    截至2014年4月,FileSytem API可能未在W3C中标准化 . 我想,任何用blob查看解决方案的人都应该小心谨慎 .

    HTML5 rocks heads up

    W3C Mailing List on FileSytem API

  • 8

    此解决方案直接从tiddlywiki(tiddlywiki.com)github存储库中提取 . 我几乎在所有浏览器中都使用了tiddlywiki,它就像一个魅力:

    function(filename,text){
        // Set up the link
        var link = document.createElement("a");
        link.setAttribute("target","_blank");
        if(Blob !== undefined) {
            var blob = new Blob([text], {type: "text/plain"});
            link.setAttribute("href", URL.createObjectURL(blob));
        } else {
            link.setAttribute("href","data:text/plain," + encodeURIComponent(text));
        }
        link.setAttribute("download",filename);
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    }
    

    Github回购:Download saver module

  • 163
    var element = document.createElement('a');
    element.setAttribute('href', 'data:text/text;charset=utf-8,' +      encodeURI(data));
    element.setAttribute('download', "fileName.txt");
    element.click();
    
  • 9

    它实际上是可能的 - 使用Flash .

    您可以使用JS生成内容,然后初始化一些flash变量或只是在flash电影中执行所有操作 .

    请查看this的一些重要评论 .

  • 4

    如前所述,filesaver是一个很好的包,可以在客户端使用文件 . 但是,大文件效果不佳 . StreamSaver.js是一个可以处理大文件的替代解决方案(在FileServer.js中指向):

    const fileStream = streamSaver.createWriteStream('filename.txt', size);
    const writer = fileStream.getWriter();
    for(var i = 0; i < 100; i++){
        var uint8array = new TextEncoder("utf-8").encode("Plain Text");
        writer.write(uint8array);
    }
    writer.close()
    
  • -33

    HTML5就绪浏览器的简单解决方案......

    function download(filename, text) {
      var element = document.createElement('a');
      element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
      element.setAttribute('download', filename);
    
      element.style.display = 'none';
      document.body.appendChild(element);
    
      element.click();
    
      document.body.removeChild(element);
    }
    
    form * {
      display: block;
      margin: 10px;
    }
    
    <form onsubmit="download(this['name'].value, this['text'].value)">
      <input type="text" name="name" value="test.txt">
      <textarea name="text"></textarea>
      <input type="submit" value="Download">
    </form>
    

    Usage

    download('test.txt', 'Hello world!');
    
  • 6

    我很高兴使用FileSaver.js . 它的兼容性非常好(IE10和其他所有东西),使用起来非常简单:

    var blob = new Blob(["some text"], {
        type: "text/plain;charset=utf-8;",
    });
    saveAs(blob, "thing.txt");
    
  • 4

    如果您只想将字符串转换为可供下载,可以使用jQuery尝试 .

    $('a.download').attr('href', 'data:application/csv;charset=utf-8,' + encodeURI(data));
    
  • 0

    以下方法适用于IE11,Firefox 25和Chrome 30:

    <a id="export" class="myButton" download="" href="#">export</a>
    <script>
        function createDownloadLink(anchorSelector, str, fileName){
            if(window.navigator.msSaveOrOpenBlob) {
                var fileData = [str];
                blobObject = new Blob(fileData);
                $(anchorSelector).click(function(){
                    window.navigator.msSaveOrOpenBlob(blobObject, fileName);
                });
            } else {
                var url = "data:text/plain;charset=utf-8," + encodeURIComponent(str);
                $(anchorSelector).attr("download", fileName);               
                $(anchorSelector).attr("href", url);
            }
        }
    
        $(function () {
            var str = "hi,file";
            createDownloadLink("#export",str,"file.txt");
        });
    
    </script>
    

    在行动中看到这个:http://jsfiddle.net/Kg7eA/

    Firefox和Chrome支持用于导航的数据URI,这允许我们通过导航到数据URI来创建文件,而IE出于安全目的不支持它 .

    另一方面,IE具有用于保存blob的API,可用于创建和下载文件 .

  • 5

    如果文件包含文本数据,我使用的技术是将文本放入textarea元素并让用户选择它(单击textarea然后按ctrl-A)然后复制,然后粘贴到文本编辑器 .

  • 3

    对我来说,这完全有效,下载的文件名和扩展名相同

    <a href={"data:application/octet-stream;charset=utf-16le;base64," + file64 } download={title} >{title}</a>

    'title'是带扩展名的文件名,即 sample.pdfwaterfall.jpg 等 .

    'file64'是这样的base64内容,即 Ww6IDEwNDAsIFNsaWRpbmdTY2FsZUdyb3VwOiAiR3JvdXAgQiIsIE1lZGljYWxWaXNpdEZsYXRGZWU6IDM1LCBEZW50YWxQYXltZW50UGVyY2VudGFnZTogMjUsIFByb2NlZHVyZVBlcmNlbnQ6IDcwLKCFfSB7IkdyYW5kVG90YWwiOjEwNDAsIlNsaWRpbmdTY2FsZUdyb3VwIjoiR3JvdXAgQiIsIk1lZGljYWxWaXNpdEZsYXRGZWUiOjM1LCJEZW50YWxQYXltZW50UGVyY2VudGFnZSI6MjUsIlByb2NlZHVyZVBlcmNlbnQiOjcwLCJDcmVhdGVkX0J5IjoiVGVycnkgTGVlIiwiUGF0aWVudExpc3QiOlt7IlBhdGllbnRO

  • 104

    适用于IE10的解决方案:(我需要一个csv文件,但它足以将类型和文件名更改为txt)

    var csvContent=data; //here we load our csv data 
    var blob = new Blob([csvContent],{
        type: "text/csv;charset=utf-8;"
    });
    
    navigator.msSaveBlob(blob, "filename.csv")
    

相关问题