Можно ли добавить к существующему файлу с помощью API доступа к файловой системе Chrome
Используя новый
File System Access API
можно читать и записывать файлы и папки на устройстве пользователя:
const newHandle = await window.showSaveFilePicker();
const writableStream = await newHandle.createWritable();
await writableStream.write("Hello World")
await writableStream.close();
Приведенный выше код напишет "Hello World" в выбранный файл. Если файл уже существует, он будет усечен и перезаписан новым содержимым.
Можно ли вместо этого добавить к существующему файлу, не читая весь файл и не записывая его снова? Хорошим примером может быть запись в файл журнала.
2 ответа
Джо Дункан прав (и спасибо за подсказку!)
Но вам нужно открыть записываемый файл в режиме «добавить».
Мне нужно закрыть/сбросить файл после записи каждой строки, а затем снова открыть, искать и добавлять в этот файл (но только 1 щелчок на кнопке «Сохранить файл»)
import {} from "wicg-file-system-access"
/**
* Supply a button-id in HTML, when user clicks the file is opened for write-append.
*
* Other code can: new LogWriter().writeLine("First line...")
* to queue writes before user clicks the button.
*
* file is flushed/closed & re-opened after every writeLine.
* (so log is already saved if browser crashes...)
*/
export class LogWriter {
fileHandle: FileSystemFileHandle;
writeablePromise: Promise<FileSystemWritableFileStream> = this.newWriterPromise;
writerReady: (value: FileSystemWritableFileStream | PromiseLike<FileSystemWritableFileStream>) => void
writerFailed: (reason?: any) => void
contents: string
get newOpenPromise () { return new Promise<FileSystemWritableFileStream>((fil, rej)=>{
this.writerReady = fil;
this.writerFailed = rej
})}
constructor(name = 'logFile', public buttonId = "fsOpenFileButton") {
const options = {
id: 'logWriter',
startIn: 'downloads', // documents, desktop, music, pictures, videos
suggestedName: name,
types: [{
description: 'Text Files',
accept: { 'text/plain': ['.txt'], },
}, ],
};
this.setButton('showSaveFilePicker', options, (value) => {
this.fileHandle = value as FileSystemFileHandle
this.openWriteable()
})
}
async openWriteable(fileHandle: FileSystemFileHandle = this.fileHandle,
options: FileSystemCreateWritableOptions = { keepExistingData: true }) {
let writeable = await fileHandle.createWritable(options)
let offset = (await fileHandle.getFile()).size
writeable.seek(offset)
this.writerReady(writeable)
}
async writeLine(text: string) {
try {
let line = `${text}\n`
let stream = (await this.openPromise) // indicates writeable is ready
await stream.seek((await this.fileHandle.getFile()).size)
await stream.write({type: 'write', data: line});
let closePromise = this.closeFile() // flush to real-file
this.openPromise = this.newOpenPromise // new Promise for next cycle:
await closePromise
while (!this.openPromise.value) await this.openWriteable()
} catch (err) {
console.warn(stime(this, `.writeLine failed:`), err)
throw err
}
}
async closeFile() {
try {
return (await this.writeablePromise).close();
} catch (err) {
console.warn(stime(this, `.closeFile failed:`), err)
throw err
}
}
/** multi-purpose picker button: (callback arg-type changes) */
setButton(method: 'showOpenFilePicker' | 'showSaveFilePicker' | 'showDirectoryPicker',
options: OpenFilePickerOptions & { multiple?: false; } & SaveFilePickerOptions & DirectoryPickerOptions,
cb: (fileHandleAry: any) => void) {
const picker = window[method] // showSaveFilePicker showDirectoryPicker
const fsOpenButton = document.getElementById(this.buttonId)
fsOpenButton.innerText = method.substring(4, method.length - 6)
fsOpenButton.onclick = () => {
picker(options).then((value: any) => cb(value), (rej: any) => {
console.warn(`showOpenFilePicker failed: `, rej)
});
}
return fsOpenButton
}
}
Вы можете получить текущий размер файла и установить позицию записи до конца:
const newHandle = await window.showSaveFilePicker();
const writableStream = await newHandle.createWritable();
// Get the current file size.
const size = (await fileHandle.getFile()).size;
await writableStream.write({
type: "write",
data: "Hello World",
position: size // Set the position to the current file size.
})
await writableStream.close();
Больше информации:
https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream/writehttps://developer.mozilla.org/en-US/docs/Web/API/IDBMutableFile/getFile