Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-67834

webassembly: support local system file access

    XMLWordPrintable

Details

    • Task
    • Resolution: Done
    • P2: Important
    • 5.14
    • None
    • QPA
    • None

    Description

      Categories of local access

      Local file system access can be divided into two categories: persisting application state and accessing user files.

      Persisting Application State

      The application wants to save state, so that the user can continue where they left later on.

      Emscripten has sandboxed file system access via FS
      https://kripken.github.io/emscripten-site/docs/api_reference/Filesystem-API.html

      Using IDBFS files can be synced to and from this sandbox. QSettings currently uses this.
      Drawbacks are that it does this asynchronously and does take some amount of time to do (after app c'tor has completed)

      Note that files synced like this are stored in a database private to the browser and are inaccessible outside of the web application.

      Accessing user files.

      The application wants to load and save user files, e.g. to enable interop with other applications and give users access to the files.

      Html5 apps can read local files via a native file dialog:
      https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications

      On the Qt side file access would preferably happen through the existing QFile and QFileDialog API, but this does not seem to be a good match for the platform:

      • We can’t block the GUI thread or re-enter the event loop; the static API won’t work
      • The native API gives us file content directly; QFileDialog returns a path which can be opened using QFile.
      • File save is not well supported (see below)

      There are various ways around this:

      • Provide OS_HTML5 specific API for working with files
        void loadFile(QStringList acceptTypes, std::function<void(QByteArray &)> dataReady);
        void saveFile(QString fileName, QByteArray contents);
      • Save the file to emscripten in-memory MEMFS, after which it can be opened with QFile. File save would still need an API, perhaps unless we can get write notifications on the file.

      Implementation details

      Qt Implementation with custom API: https://codereview.qt-project.org/#/c/228599/

      Stage 1: to JavasScript memory

      Prototype https://github.com/msorvig/qt-webassembly-examples/blob/master/html_localfiles/index.html

      Load: HTML5 supports showing a native file dialog via <input type="file”>, which gives a FileList, whose File entries can be read by a FileReader (asyncly) to produce an ArrayBuffer.

      FileList https://developer.mozilla.org/en-US/docs/Web/API/FileList
      FileReader: https://developer.mozilla.org/en-US/docs/Web/API/FileReader

      Save: There is no corresponding file save API. Instead. we can create a data download link (window.URL.createObjectURL), and then programmatically trigger it.

      https://stackoverflow.com/questions/32326973/file-write-operation-in-javascript

      This is not really “file save”, it's rather “file download”. The file save destination will be the standard download directory

      Stage 2 a): To C++ memory

      ArrayBuffer <-> QByteArray

      emscripten prototype: https://github.com/msorvig/qt-webassembly-examples/tree/master/emscripten_localfiles

      Stage 2 b): To the in-memory file system

      FS.writeFile(“/tmp/foofile”, arrayBuffer)

      Attachments

        For Gerrit Dashboard: QTBUG-67834
        # Subject Branch Project Status CR V

        Activity

          People

            sorvig Morten Sørvig
            lpotter Lorn Potter
            Votes:
            11 Vote for this issue
            Watchers:
            23 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes