[whatwg] Drag-and-drop folders/files support with directory structure using DirectoryEntry

A follow up about this proposal:

Based on the feedbacks we got on this list we've implemented the following
API to do experiments in Chrome:
 DataTransferItem.getAsEntry(in EntryCallback callback)

which takes a callback that returns FileEntry or DirectoryEntry if it's for
drop event and the item's kind is 'file'.
Right now it's prefixed therefore its actual name in Chrome is
'webkitGetAsEntry'.
We use kind=='file' in a broader definition here (i.e. a file path which
can be either regular file or directory file) and didn't add a specific
kind for directories.
(Btw we've also implemented DataTransferItem.getAsFile(), so apps can call
either getAsFile or webkitGetAsEntry for kind=='file' item)

As for lifetime and toURL() issue, which was the biggest concern in the
past discussion, we decided not to support toURL/resolveURL on  Entries for
drag-and-drop, so that it won't leak reference or expose GC period.  A
dragged file can be accessed only while the script has the Entry instance
(as well as we do for File object).  We eventually aim to support
structured cloning of Entries but it's not there yet.

Each Entry returned by this API has following properties:
* is read-only.
* has the dropped file/directory name (not a full path) in its
Entry.name, which must also match with the basename of Entry.fullPath.
* should not expose the actual platform path, but how exactly its fullPath
should look is implementation dependent. (In our implementation it always
appears as a top-level path, e.g. '/foo' for a file/directory 'foo')

Example:
If we drop multiple files/directories like following:
 /User/kinuko/Photos/travel/thailand/
 /User/kinuko/Photos/holiday2012/
 /User/kinuko/Photos/photos.txt

We'll get three kind=='file' items in dataTransfer.items, and
calling getAsEntry (webkitGetAsEntry) on each item allow us to get
FileEntry or DirectoryEntry and to recursively traverse its child
files/subdirectories with full control if it's directory.

  var items = e.dataTransfer.items;
  for (var i = 0; i < items.length; ++i) {
    if (items[i].kind == 'file') {
      items[i].webkitGetAsEntry(function(entry) {
        displayEntry(entry.name + (entry.isDirectory ? ' [dir]' : ''));
        ...
      });
    }
  }

As for <input type="file"> support I am thinking about adding "AsEntries"
attribute (so that we do not need to do the automatic recursive
files/directories retrieval when the attribute is specified) and "entries"
field, but haven't done anything yet.  (Open to further suggestions)

I hope we can get valuable user feedbacks (as well as from yours) based on
the implementation.


On Sat, Nov 19, 2011 at 7:37 AM, Glenn Maynard <glenn at zewt.org> wrote:

> On Fri, Nov 18, 2011 at 1:36 AM, Kinuko Yasuda <kinuko at chromium.org>wrote:
>
>> I would say the approach has a bloating per-page bookkeeping problem but
>> not a 'leak'.
>
>
> It's a reference leak: an object which remains referenced after it's no
> longer needed.  I'm not aware of anything standardized in the platform with
> this problem.  Also, a lot of toURL use cases would simply not work with
> drag-and-dropped files (being able to modify the URL to access neighboring
> files; storing the URL for access in a future session).
>
> Anyway, do you still agree that having Entry structured clonable is a good
> idea?  I'm only really worried about toURL if it causes structured cloning
> of Entry to not happen, since I think the latter is a much more solid and
> useful approach, and more consistent with what we already have.
> (Half-solutions make me nervous, because they have a tendency to delay full
> solutions.)
>
> --
> Glenn Maynard
>
>

Received on Wednesday, 4 April 2012 21:36:59 UTC