Signatur
Beschreibung
Die Methode createWriter() gehört zur älteren File and Directory Entries API und gibt über einen Callback ein FileWriter-Objekt zurück. Damit kann man in die Datei schreiben, auf die der Eintrag verweist, darin mit seek() springen und sie mit truncate() kürzen oder verlängern. Das Ergebnis kommt nicht direkt als Rückgabewert und auch nicht als Promise, sondern nur über den übergebenen successCallback.
Einen beschreibbaren Eintrag bekommt man in der Praxis nur aus einem sandboxed Dateisystem, das man mit window.webkitRequestFileSystem() anfordert. Einträge aus Drag & Drop (DataTransferItem.webkitGetAsEntry()) oder aus <input type="file" webkitdirectory> kann man nur lesen. Dort schlägt createWriter() fehl oder steht gar nicht erst zur Verfügung.
FileWriter schreibt asynchron und ereignisbasiert. Jede Operation (write(), truncate()) löst unter anderem writeend oder error aus. Während eine Operation läuft, darf keine zweite starten, sonst gibt es einen InvalidStateError. Mehrere Schreibvorgänge muss man deshalb nacheinander ausführen, zum Beispiel indem man den nächsten erst in onwriteend startet.
Für neue Projekte sollte man die moderne File System API verwenden: FileSystemFileHandle.createWritable() (Origin Private File System über navigator.storage.getDirectory() oder showSaveFilePicker()). Sie arbeitet mit Promises und Streams.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $successCallback Pflicht | (writer: FileWriter) => void | Wird mit dem erzeugten FileWriter aufgerufen, sobald der Writer bereit ist. |
|
| $errorCallback | (error: DOMException | FileError) => void | Wird aufgerufen, wenn kein Writer erzeugt werden kann, z. B. weil die Datei fehlt (NotFoundError), der Zugriff verweigert wird (SecurityError) oder der Eintrag schreibgeschützt ist. |
Rückgabewert
FileWriter wird an successCallback übergeben.Beispiele
Textdatei im Sandbox-Dateisystem anlegen und beschreiben
const onError = (err) => console.error('Fehler:', err.name, err.message);
window.webkitRequestFileSystem(window.TEMPORARY, 1024 * 1024, (fs) => {
fs.root.getFile('notizen.txt', { create: true }, (fileEntry) => {
fileEntry.createWriter((writer) => {
writer.onwriteend = () => console.log('Geschrieben, Länge:', writer.length);
writer.onerror = (e) => console.error('Schreibfehler:', e.target.error);
const blob = new Blob(['Hallo Welt!\n'], { type: 'text/plain' });
writer.write(blob);
}, onError);
}, onError);
}, onError);
Promise-Wrapper und Daten ans Dateiende anhängen
// Callback-API in Promises verpacken
const getWriter = (fileEntry) =>
new Promise((resolve, reject) => fileEntry.createWriter(resolve, reject));
const writeBlob = (writer, blob) =>
new Promise((resolve, reject) => {
writer.onwriteend = resolve;
writer.onerror = () => reject(writer.error);
writer.write(blob);
});
const appendLog = async (fileEntry, line) => {
const writer = await getWriter(fileEntry);
writer.seek(writer.length); // ans Ende springen
await writeBlob(writer, new Blob([`${new Date().toISOString()} ${line}\n`]));
console.log('Neue Dateigröße:', writer.length);
};
// Aufruf, z. B.: await appendLog(fileEntry, 'App gestartet');
Datei leeren und danach neu schreiben (sequenziell)
const overwrite = (fileEntry, text) => {
fileEntry.createWriter((writer) => {
let truncated = false;
writer.onwriteend = () => {
if (!truncated) {
truncated = true;
// erst nach Abschluss von truncate() schreiben
writer.write(new Blob([text], { type: 'text/plain' }));
} else {
console.log('Datei ersetzt:', writer.length, 'Bytes');
}
};
writer.onerror = () => console.error(writer.error);
writer.truncate(0);
}, (err) => console.error(err));
};
// overwrite(fileEntry, 'Neuer Inhalt');
Moderne Alternative: FileSystemFileHandle.createWritable()
const root = await navigator.storage.getDirectory(); // Origin Private File System
const handle = await root.getFileHandle('notizen.txt', { create: true });
const writable = await handle.createWritable();
await writable.write('Hallo Welt!\n');
await writable.close();
const file = await handle.getFile();
console.log(await file.text());
// Wichtig · Fallstricke
- Nicht standardisiert und veraltet:
createWriter()undFileWritergibt es nur in Chromium-basierten Browsern (Chrome, Edge, Opera) und nur zusammen mitwebkitRequestFileSystem(). Firefox und Safari unterstützen zwarFileSystemFileEntry(nur lesend überfile()),createWriter()aber nicht. Vor der Nutzung sollte man die Funktion prüfen:typeof entry.createWriter === 'function'. - Kein Schreibzugriff auf Dateien des Nutzers: Einträge aus Drag & Drop oder aus Dateiauswahl-Dialogen sind schreibgeschützt. Man kann nur in das sandboxed Dateisystem des eigenen Origins schreiben.
- Keine parallelen Operationen: Ruft man
write()odertruncate()auf, während noch ein Vorgang läuft (readyState === FileWriter.WRITING), gibt es einenInvalidStateError. Der nächste Aufruf gehört inonwriteend. - Überschreiben statt Ersetzen:
write()schreibt ab der aktuellenposition. Ist der neue Inhalt kürzer, bleiben alte Daten am Ende stehen. Deshalb vorhertruncate(0)aufrufen oder mitseek(writer.length)gezielt anhängen. - Kontingent: Bei
TEMPORARY-Speicher darf der Browser die Daten jederzeit löschen. Wird das Kontingent überschritten, gibt es einenQuotaExceededError. - Nur in sicheren Kontexten (HTTPS) zuverlässig. Für neuen Code
FileSystemFileHandle.createWritable()oder in WorkerncreateSyncAccessHandle()verwenden.