hpoul / file_picker_writable

Flutter plugin to choose files which can be read, referenced and written back at a later time.
https://pub.dev/packages/file_picker_writable
MIT License
17 stars 13 forks source link

Coordinate file access to prevent stale content on iOS #17

Closed amake closed 3 years ago

amake commented 3 years ago

A long-standing problem I've had with FilePickerWritable on iOS is that re-reading a file will show stale content despite the remote file having been updated. I finally figured out why.

When reading a file you need to coordinate the read with NSFileCoordinator which will do things like ensure writes don't happen concurrently with reads or with other writes. Another thing it does is download the content from the content provider:

If the device has not yet downloaded the file at the given URL, this method blocks (potentially for a long time) while the file is downloaded. If the file cannot be downloaded, this method fails. Alternatively; use a metadata query to check for the NSMetadataUbiquitousItemDownloadingStatusKey key, and then call the startDownloadingUbiquitousItem(at:) method to download the file before trying to read it.

(source)

startDownloadingUbiquitousItem(at:), which presumably is called under the hood, not only downloads missing files, but it also updates them:

If a cloud-based file or directory has not been downloaded yet, calling this method starts the download process. If the item exists locally, calling this method synchronizes the local copy with the version in the cloud.

(source)

Note that I do the copy twice because file coordination can fail if the device is offline (tested with Google Drive). In that case I would prefer to have access to the cached file, if present, than to fail entirely.

(Doing the copy just once after coordinating is also possible, but then you lose out on the guarantee that no writes will happen concurrently with your read. So as ugly as it is this was the best solution I could think of.)

hpoul commented 3 years ago

That's interesting.. thanks, looks good to me 👍️