Ошибка записи в файлы с использованием API доступа к файловой системе в приложении Electron + Create React

У меня есть приложение create-response-app, которое читает и записывает локальные файлы с помощью API доступа к файловой системе . При запуске в браузере (Chrome или Edge, которые его поддерживают) чтение и запись файлов работают нормально.

Когда приложение запущено в Electron, чтение работает, но запись не выполняется из-за: Uncaught (in promise) DOMException: The request is not allowed by the user agent or the platform in the current context.

Я использую последнюю версию Electron (12.0.1), в которой используется тот же Chromium (89.0.4389.82), что и в моем браузере Chrome.

Ниже приведен соответствующий код. Журнал консоли после requestPermission звонки шоу и granted в браузере и true и denied в электрон.

Я пробовал отключить webSecurity при создании BrowserWindow, отключение песочницы с помощью appendSwitch но ничего не помогло.

Есть ли способ предоставить Chromium in Electron больше разрешений?

Если нет, я готов по-другому обрабатывать запись файлов в Electron. В таком случае, что писать вместо TODOв коде? Обратите внимание: поскольку это приложение create-response-app, fsмодуль недоступен .

      export async function chooseAndReadFile() {
    const fileHandle = await window.showOpenFilePicker().then((handles) => handles[0])
    const file = await fileHandle.getFile()
    const contents = await file.text()
    return contents
}

export async function chooseAndWriteToFile(contents: string) {
    const fileHandle = await window.showSaveFilePicker()

    const descriptor: FileSystemHandlePermissionDescriptor = {
        writable: true,
        mode: "readwrite"
    }
    const permissionState = await fileHandle.requestPermission(descriptor)
    console.log(window.isSecureContext)
    console.log(permissionState)

    const writable = await fileHandle.createWritable()
    await writable.write(contents)
    await writable.close()
}

let isElectron = require("is-electron")
export async function chooseAndWriteToFileUniversal(contents: string) {
    if (isElectron()) {
        // TODO: Do what???
    } else {
        chooseAndWriteToFile(contents)
    }
}

1 ответ

Отвечая на свой вопрос, я наконец использовал решение с HTML downloadатрибут, красиво описанный здесь . Когда этот метод используется в Electron, он представляет диалог сохранения файла, который мне и нужен. При использовании в браузере этот метод просто загружает файл без запроса, поэтому я продолжу использовать API доступа к файловой системе для браузерных сред.

Вот код, который обрабатывает загрузку при работе в Electron.

      function download(filename: string, contents: string) {
    var element = document.createElement('a');
    element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(contents));
    element.setAttribute('download', filename);
    element.style.display = 'none';
    document.body.appendChild(element);

    element.click();

    document.body.removeChild(element);
}

let isElectron = require("is-electron");
export async function chooseAndWriteToFileUniversal(contents: string) {
    if (isElectron()) {
        download("data.txt", contents)
    } else {
        chooseAndWriteToFile(contents) // See the original question for implementation of this function
    }
}

Тем не менее, было бы неплохо узнать, почему / как Chromium в Electron более ограничен, чем в обычном браузере Chrome или Edge, и можно ли его изменить.

Другие вопросы по тегам