Dosyaya yalnızca JavaScript kullanarak veri yazmak mümkün müdür?


192

JavaScript kullanarak mevcut dosyaya Veri Yazmak istiyorum. Konsolda yazdırmak istemiyorum. Verileri Aslında Yazmak İstiyorum abc.txt. Cevaplanan birçok soruyu okudum ama her yerde konsola yazdırıyorlar. bir yerde onlar kod verdik ama onun çalışmıyor. Yani herhangi biri bana gerçekten Dosyaya veri yazma nasıl yardımcı olabilir.

Kodu sevk ama çalışmıyor: onun veren hata:

Yakalanmayan TypeError: Yasadışı kurucu

krom ve

SecurityError: İşlem güvenli değil.

Mozilla'da

var f = "sometextfile.txt";

writeTextFile(f, "Spoon")
writeTextFile(f, "Cheese monkey")
writeTextFile(f, "Onion")

function writeTextFile(afilename, output)
{
  var txtFile =new File(afilename);
  txtFile.writeln(output);
  txtFile.close();
}

Yani aslında sadece Javascript veya NOT kullanarak dosyaya veri yazabilir miyiz?



Yanıtlar:


90

Bunun için bazı öneriler -

  1. İstemci makineye bir dosya yazmaya çalışıyorsanız, bunu herhangi bir çapraz tarayıcı yöntemiyle yapamazsınız. IE, "güvenilir" uygulamaların dosyayı okumak / yazmak için ActiveX nesnelerini kullanmasını sağlayan yöntemlere sahiptir.
  2. Sunucunuza kaydetmeye çalışıyorsanız, metin verilerini sunucunuza iletin ve sunucu yazma dilini kullanarak dosya yazma kodunu yürütün.
  3. İstemci tarafında oldukça küçük bazı bilgileri saklamak için çerezleri kullanabilirsiniz.
  4. Yerel Depolama için HTML5 API'sini kullanma.

27
HTML5 API'sı yalnızca 5 mb'dir.
Pacerier

Evet, seçmeden sistem dosyasına yazamazsınız. Resmi Belgeleri Okuyun: w3.org/TR/file-upload/#security-discussion
Manoj Ghediya

217

Sen kullanarak tarayıcıda dosyaları oluşturabilir Blobve URL.createObjectURL. Tüm yeni tarayıcılar bunu desteklemektedir .

Oluşturduğunuz dosyayı doğrudan kaydedemezsiniz, çünkü bu büyük güvenlik sorunlarına neden olur, ancak kullanıcı için bir indirme bağlantısı olarak sağlayabilirsiniz. İndirme özelliğini destekleyen tarayıcılarda, bağlantının downloadniteliği aracılığıyla bir dosya adı önerebilirsiniz . Diğer indirme işlemlerinde olduğu gibi, dosyayı indiren kullanıcı dosya adında son söze sahip olacaktır.

var textFile = null,
  makeTextFile = function (text) {
    var data = new Blob([text], {type: 'text/plain'});

    // If we are replacing a previously generated file we need to
    // manually revoke the object URL to avoid memory leaks.
    if (textFile !== null) {
      window.URL.revokeObjectURL(textFile);
    }

    textFile = window.URL.createObjectURL(data);

    // returns a URL you can use as a href
    return textFile;
  };

İşte a'dan rastgele metin kaydetmek için bu tekniği kullanan bir örnektextarea .

Eğer bir linke tıklayın kullanıcının gerek yerine indirmeyi başlatan hemen istiyorsanız, siz linke bir klik simüle etmek için fare etkinlikleri kullanabilirsiniz Lifecube 'ın cevabı yaptı. Bu tekniği kullanan güncellenmiş bir örnek oluşturdum .

  var create = document.getElementById('create'),
    textbox = document.getElementById('textbox');

  create.addEventListener('click', function () {
    var link = document.createElement('a');
    link.setAttribute('download', 'info.txt');
    link.href = makeTextFile(textbox.value);
    document.body.appendChild(link);

    // wait for the link to be added to the document
    window.requestAnimationFrame(function () {
      var event = new MouseEvent('click');
      link.dispatchEvent(event);
      document.body.removeChild(link);
    });

  }, false);

1
@FirstBlood Hangi kısım çalışmıyor, bir hata mı alıyorsunuz? Dosya ve bağlantı oluşturma Safari 7+ çalışmalıdır (Ben ön ekli sürümünü kullanırsanız şeyler Safari 6 kullanarak da çalışması gerektiğini düşünüyorum URL). Dosya adını ayarlamak Safari'de hala çalışmadığından, downloadözniteliği hala uygulamadı .
Yararsız Kod

1
Safari 5.1'de
First Blood

1
kaydedilen doktorda yeni çizgi karakteri eksik
Benny

1
@Benny newline karakterleri orada. JS, \nUNIX programları gibi yeni satırları temsil etmek için yeni satır karakterini kullanır . Muhtemelen karakteri yeni bir satır olarak oluşturmayan\n Not Defteri gibi bir Windows programında görüntülüyorsunuz . Yeni satırlar doğru metin koymadan önce, Not Defteri ve bazı diğer Windows programlarında işlenecek isterseniz Blobher yerini \nile \r\n: text = text.replace(/\n/g, '\r\n').
Yararsız Kod

2
@ user3241111 Pek değil, işe yaramalı. Bunun gibi şeyler olağandışı değil. Bunu yapmanın hackyer yollarını gördüm ;-) Geçmişte ben de sadece mouseoverbağlantı üzerinde dosyayı oluşturmakla kaçtım , ama ne kadar işleme bağlı olarak büyük işe yaramayabilir bağlı.
Yararsız Kod

41

Tarayıcı javascriptinden bahsediyorsanız, güvenlik nedeniyle doğrudan yerel dosyaya veri yazamazsınız. HTML 5 yeni API yalnızca dosyaları okumanıza izin verebilir.

Ancak, veri yazmak ve kullanıcının yerel olarak bir dosya olarak indirmesini sağlamak istiyorsanız. aşağıdaki kod çalışır:

    function download(strData, strFileName, strMimeType) {
    var D = document,
        A = arguments,
        a = D.createElement("a"),
        d = A[0],
        n = A[1],
        t = A[2] || "text/plain";

    //build download link:
    a.href = "data:" + strMimeType + "charset=utf-8," + escape(strData);


    if (window.MSBlobBuilder) { // IE10
        var bb = new MSBlobBuilder();
        bb.append(strData);
        return navigator.msSaveBlob(bb, strFileName);
    } /* end if(window.MSBlobBuilder) */



    if ('download' in a) { //FF20, CH19
        a.setAttribute("download", n);
        a.innerHTML = "downloading...";
        D.body.appendChild(a);
        setTimeout(function() {
            var e = D.createEvent("MouseEvents");
            e.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
            a.dispatchEvent(e);
            D.body.removeChild(a);
        }, 66);
        return true;
    }; /* end if('download' in a) */



    //do iframe dataURL download: (older W3)
    var f = D.createElement("iframe");
    D.body.appendChild(f);
    f.src = "data:" + (A[2] ? A[2] : "application/octet-stream") + (window.btoa ? ";base64" : "") + "," + (window.btoa ? window.btoa : escape)(strData);
    setTimeout(function() {
        D.body.removeChild(f);
    }, 333);
    return true;
}

kullanmak için:

download('the content of the file', 'filename.txt', 'text/plain');


Şaşırtıcı, Lifecube. Bu işlevselliğe gerçekten ihtiyacım vardı, ancak kullanıcının herhangi bir dosyanın indirildiğini bilmesini istemiyorum, bazı eylemlerin ardından bazı dosyaların otomatik olarak indirildiğini görmek için kullanıcıyı korkutabileceği için kullanıcıdan tamamen gizli olmasını istiyorum. bir web sitesinde, yalnızca pazarlama verilerinin toplanması amacıyla kullanmamıza rağmen, dosyayı kullanıcı için görünür yapmadan nasıl indireceğinizi paylaşabilir misiniz?
Just_another_developer

1
Yukarıdaki çözüm biraz modası geçmiş. Html 5 javascript lib'i dikkate almanız gerekebilir. github.com/eligrey/FileSaver.js
Lifecube

@Lifecube FileSaver.js kullanarak, kullanıcı etkileşimi olmadan metni otomatik olarak bir dosyaya kaydetmenin bir yolu var mı? Teşekkürler! JS'de yeni; tüm yardımlarınız takdir
Nathan

3
Bir dosyayı kullanıcı bilmeden kaydetmeyle ilgili birkaç soruya: Böyle bir davranış, tasarımdan kaçınılan şeydir. Bu, bir Pandora'nın kullanımı kolay güvenlik tehditleri kutusunu açacaktır. Çerezler pazarlama amacıyla veri toplamak içindir.
Ari Okkonen

Not Windows 10'da firefox v76'da bir html dosyasını .html olarak indirmek için bulamıyorum. İndirme işleminin sonuna .pdf dosyası eklenmiştir.
CSchwarz

23

Yukarıdaki yanıt yararlıdır, ancak metin dosyasını doğrudan düğme tıklatmasına indirmenize yardımcı olan kod buldum . Bu kodda istediğiniz gibi değiştirebilirsiniz filename. HTML5 ile saf javascript işlevi. Benim için çalışıyor!

function saveTextAsFile()
{
    var textToWrite = document.getElementById("inputTextToSave").value;
    var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});
    var fileNameToSaveAs = document.getElementById("inputFileNameToSaveAs").value;
      var downloadLink = document.createElement("a");
    downloadLink.download = fileNameToSaveAs;
    downloadLink.innerHTML = "Download File";
    if (window.webkitURL != null)
    {
        // Chrome allows the link to be clicked
        // without actually adding it to the DOM.
        downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
    }
    else
    {
        // Firefox requires the link to be added to the DOM
        // before it can be clicked.
        downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
        downloadLink.onclick = destroyClickedElement;
        downloadLink.style.display = "none";
        document.body.appendChild(downloadLink);
    }

    downloadLink.click();
}

2
Mükemmel. Opera'da benim için çalışıyor. Bilinmeyen işlevi değiştirme ihtiyacı hariç: "destroyClickedElement" ifadesi ile "document.body.removeChild (event.target)"
steveOw

3
Kullanırken dikkatli olmalısınız createObjectURL. JS'deki çoğu şeyden farklı olarak, onunla oluşturduğunuz nesneler, bunlara daha fazla referans olmadığında otomatik olarak toplanmaz; yalnızca sayfa kapandığında toplanan çöplerdir. Eğer kullandığınız Since URL.revokeObjectURL()son çağrı tarafından kullanılan bellek boşaltmak için bu kodda, bir bellek sızıntısı var; kullanıcı saveTextFilebirden çok kez ararsa , daha önce hiç bırakmadığınız için daha fazla bellek tüketmeye devam eder.
Yararsız Kod

20

Deneyin

let a = document.createElement('a');
a.href = "data:application/octet-stream,"+encodeURIComponent("My DATA");
a.download = 'abc.txt';
a.click();


6

Yeni Blobçözümü, yani modern tarayıcıdaki en iyi çözümü kullanmak mümkün değilse , dosya boyutunda bu arada bir sınırı olan bu daha basit yaklaşımı kullanmak hala mümkündür:

function download() {
                var fileContents=JSON.stringify(jsonObject, null, 2);
                var fileName= "data.json";

                var pp = document.createElement('a');
                pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
                pp.setAttribute('download', fileName);
                pp.click();
            }
            setTimeout(function() {download()}, 500);

$('#download').on("click", function() {
  function download() {
    var jsonObject = {
      "name": "John",
      "age": 31,
      "city": "New York"
    };
    var fileContents = JSON.stringify(jsonObject, null, 2);
    var fileName = "data.json";

    var pp = document.createElement('a');
    pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
    pp.setAttribute('download', fileName);
    pp.click();
  }
  setTimeout(function() {
    download()
  }, 500);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="download">Download me</button>


3

Dosyayı oluşturmak için kullanıcının @ @ yararsız kodunun ( https://stackoverflow.com/a/21016088/327386 ) kodunu kullanın. Dosyayı otomatik olarak indirmek istiyorsanız textFile, yeni oluşturulan dosyayı bu işleve iletin:

var downloadFile = function downloadURL(url) {
    var hiddenIFrameID = 'hiddenDownloader',
    iframe = document.getElementById(hiddenIFrameID);
    if (iframe === null) {
        iframe = document.createElement('iframe');
        iframe.id = hiddenIFrameID;
        iframe.style.display = 'none';
        document.body.appendChild(iframe);
    }
    iframe.src = url;
}

5
Bunun neden aşağı oyu olduğunu bilmiyorum. Benim için çalışıyor. Aşağı oy kullanan kişiler en azından bunun neden aşağı oy verildiğine ilişkin bir yorum bırakmalıdır!
RPM

5
Oy vermedim, ama aslında oy hakkında yorum yapmak doğrudan cesaretini kırıyor. Kullanıcı bir gönderinin içeriğine yorum yapmalı ve bir gönderinin içeriğine oy vermelidir, ancak oyları hakkında yorum yapmamalıdır. Birisi yorum yapmadan oy kullanırsa, bu oy kullanmanıza bağlı olarak "bu cevap yararlıdır" veya "bu cevap yararlı değildir" anlamına gelebilir.

Bu çalışmıyor .. Dosyayı indirmiyor. Sadece gizli bir iframe oluşturur. Chrome ve Firefox'ta test ettim
NaiveCoder

2

Burada iyi cevaplar buldum, ancak daha basit bir yol buldum.

Blob ve indirme bağlantısı oluşturma düğmesi, bağlantı öğesi bir onclick özniteliğine sahip olabileceğinden tek bir bağlantıda birleştirilebilir. (Tersi mümkün görünmüyor, bir düğmeye bir href eklemek işe yaramıyor.)

Kullanarak bağlantıyı düğme olarak biçimlendirebilirsiniz bootstrap , stil hariç, hala saf javascript olan şekillendirebilirsiniz.

Düğmeyi ve indirme bağlantısını birleştirmek de kodları azaltır; getElementById aramalardan daha ihtiyaç duyulduğundan .

Bu örnekte metin blobunu oluşturmak ve indirmek için yalnızca bir düğme tıklaması gerekir:

<a id="a_btn_writetofile" download="info.txt" href="#" class="btn btn-primary" 
   onclick="exportFile('This is some dummy data.\nAnd some more dummy data.\n', 'a_btn_writetofile')"
>
   Write To File
</a>

<script>
    // URL pointing to the Blob with the file contents
    var objUrl = null;
    // create the blob with file content, and attach the URL to the downloadlink; 
    // NB: link must have the download attribute
    // this method can go to your library
    function exportFile(fileContent, downloadLinkId) {
        // revoke the old object URL to avoid memory leaks.
        if (objUrl !== null) {
            window.URL.revokeObjectURL(objUrl);
        }
        // create the object that contains the file data and that can be referred to with a URL
        var data = new Blob([fileContent], { type: 'text/plain' });
        objUrl = window.URL.createObjectURL(data);
        // attach the object to the download link (styled as button)
        var downloadLinkButton = document.getElementById(downloadLinkId);
        downloadLinkButton.href = objUrl;
    };
</script>

0

Evet bu mümkün Kod burada

const fs = require('fs') 
let data = "Learning how to write in a file."
fs.writeFile('Output.txt', data, (err) => { 
      
    // In case of a error throw err. 
    if (err) throw err; 
}) 

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.