파일 및 디렉터리 항목 API

커뮤니티 그룹 초안 보고서,

이번 버전:
https://wicg.github.io/entries-api/
테스트 스위트:
https://github.com/web-platform-tests/wpt/tree/master/entries-api
이슈 트래킹:
GitHub
명세 내 인라인
에디터:
(Google Inc.)

요약

이 명세서는 웹 브라우저에서 파일 및 디렉터리 업로드를 드래그 앤 드롭 작업으로 지원하는 내용을 문서화합니다. 비동기적으로 디렉터리를 탐색할 수 있는 메서드를 가진 디렉터리 타입을 도입하며, HTMLInputElementDataTransferItem [HTML]을 확장합니다.

이 문서의 상태

이 명세서는 Web Platform Incubator Community Group에서 발행되었습니다. W3C 표준이 아니며 W3C 표준 트랙에도 포함되어 있지 않습니다. W3C 커뮤니티 기여자 라이선스 계약 (CLA)에 따라 제한적 옵트아웃 및 기타 조건이 적용됩니다. W3C 커뮤니티 및 비즈니스 그룹에 대해 자세히 알아보세요.

1. 목표

이 명세서는 웹 브라우저가 스크립트에 제공하는 파일 및 디렉터리 계층 구조를 페이지에 드래그 앤 드롭하거나 폼 요소를 통해 선택하거나, 그에 준하는 사용자 동작을 수행할 때 제공되는 타입과 동작을 문서화합니다.

이는 샌드박스 파일 시스템 환경에서 유사한 타입과 파일 및 디렉터리 생성/수정 동작을 정의하지만, 웹 브라우저에서 널리 채택되지 않은 [file-system-api]의 초기 초안에 크게 기반하고 있습니다.

note: 이 문서에서 설명하는 API는 최초로 Google Chrome에 구현되었습니다. 현재(이 시점에서: Edge, Firefox, Safari) 다른 브라우저들도 Chrome의 일부 API와 동작을 부분적으로 지원하기 시작했습니다. 이 문서의 목적은 구현체들이 상호 운용될 수 있도록 공통 부분을 명세하는 데 있습니다.

2. 개념

2.1. 이름과 경로

name은 다음을 만족하는 문자열입니다:

path segmentname, '.' (U+002E FULL STOP) 또는 '..' (U+002E FULL STOP, U+002E FULL STOP)입니다.

relative path는 하나 이상의 path segment가 '/' (U+002F SOLIDUS)로 연결된 문자열로, '/' (U+002F SOLIDUS)로 시작하지 않습니다.

absolute path는 '/' (U+002F SOLIDUS)로 시작하고, 그 뒤에 0개 이상의 path segment가 '/' (U+002F SOLIDUS)로 연결된 문자열입니다.

pathrelative path 또는 absolute path입니다.

valid pathUSVString 타입이며, path입니다.

2.2. 파일 및 디렉터리

file은 바이너리 데이터와 name (비어 있지 않은 name)으로 구성됩니다.

directoryname (name)과 멤버의 순서 있는 리스트로 구성됩니다. 각 멤버는 file 또는 directory입니다. directory의 각 멤버는 고유한 비어 있지 않은 name을 가져야 합니다.

root directorydirectory이며, 다른 directory의 멤버가 아닙니다. root directoryname은 비어 있습니다.

parentfile 또는 directory가 속한 directory입니다. root directoryparent가 없습니다.

편집: directoryfile의 특수 타입으로 정의하여 [HTML]에서 최소한의 변경만 필요하도록 해야 할까요?

note: 대부분의 경우, 사용자가 선택한 파일과 디렉터리는 실제 네이티브 파일 시스템에 존재하지 않는 가상 루트에 포함된 것처럼 API에서 표시됩니다.

파일 시스템이름루트(연관된 루트 디렉터리)로 구성됩니다. 이름파일 시스템마다 고유한 USVString 타입이며, 구현에 따라 정의됩니다. 루트 디렉터리는 정확히 하나의 파일 시스템에 연관됩니다.

참고: 구현체는 각 이름을 생성할 때, 파일 시스템 인스턴스마다 UUID를 만들고, 고정된 접두사와 접미사를 적용할 수 있습니다. API를 사용하는 작성자는 이름의 구조나 내용에 대해 가정하지 않는 것이 좋습니다.

2.3. 항목

entryfile entry 또는 directory entry입니다.

entryname (name)과 full path (absolute path)를 가집니다.

entryroot도 가지며, 연관된 root directory입니다.

note: entryroot directory를 기준으로 한 path로 정의됩니다. 이는 API와 상호작용하는 네이티브 파일 시스템이 디렉터리 내용 열거와 같은 작업 중에 비동기적으로 변경될 수 있음을 고려한 것입니다. entry에 노출된 동작은 path가 더 이상 동일한 엔티티를 참조하지 않을 경우 오류를 발생시킬 수 있습니다.

file systementryroot에 연관된 file system입니다.

3. 알고리즘

abspath (절대 경로)와 path (절대 경로, 상대 경로 또는 빈 문자열)로 상대 경로를 해석하기를 수행하려면 다음 단계를 따른다. 반환값은 절대 경로이다.

  1. path절대 경로라면, path를 반환한다.

  2. abspath segments엄격하게 분할하여 abspath를 '/' (U+002F SOLIDUS) 기준으로 나눈 결과로 한다.

    note: 첫 번째 문자열은 빈 값이다.

  3. path segments엄격하게 분할하여 path를 '/' (U+002F SOLIDUS) 기준으로 나눈 결과로 한다.

  4. path segments의 각 segment에 대해 다음을 수행한다:

    빈 문자열

    계속한다.

    '.' (U+002E FULL STOP)

    계속한다.

    '..' (U+002E FULL STOP, U+002E FULL STOP)

    abspath segments의 마지막 멤버를 제거한다. 단, 그 멤버가 유일한 멤버라면 제거하지 않는다.

    그 외

    segmentabspath segments에 추가한다.

  5. abspath segments를 '/' (U+002F SOLIDUS)로 연결하여 반환한다.

directory (루트 디렉터리)와 path (절대 경로)로 경로 평가하기를 수행하려면 다음 단계를 따른다. 반환값은 파일, 디렉터리 또는 실패이다.

  1. segments엄격하게 분할하여 path를 '/' (U+002F SOLIDUS) 기준으로 나눈 결과로 한다.

  2. segments의 첫 번째 항목을 제거한다.

    note: path절대 경로이므로, 첫 번째 항목은 항상 빈 값이다.

  3. segments의 각 segment에 대해 다음을 수행한다:

    빈 문자열

    계속한다.

    '.' (U+002E FULL STOP)

    계속한다.

    '..' (U+002E FULL STOP, U+002E FULL STOP)

    directorydirectory상위로 지정한다. 만약 상위가 없다면 directory 자신을 그대로 사용한다.

    그 외

    다음 단계를 수행한다:

    1. itemdirectory에서 namesegment와 동일한 멤버로 지정한다. 없다면 실패를 반환한다.

    2. segmentsegments의 마지막 항목이라면, item을 반환한다.

    3. item파일이라면, 실패를 반환한다.

    4. directoryitem으로 지정한다.

4. File 인터페이스

편집: 이 섹션은 완성되면 [FileAPI]에 병합되어야 합니다.
partial interface File {
    readonly attribute USVString webkitRelativePath;
};

webkitRelativePath getter 단계는 this상대 경로를 반환하거나, 지정되지 않았다면 빈 문자열을 반환한다.

5. HTML: 폼

편집: 이 섹션은 완성되면 [HTML]에 병합되어야 합니다. 엔트리 리스트 생성 단계 등은 webkitRelativePath 속성을 포함하도록 확장되어야 합니다.
partial interface HTMLInputElement {
    attribute boolean webkitdirectory;
    readonly attribute FrozenArray<FileSystemEntry> webkitEntries;
};

input 요소의 type 속성이 파일 업로드 상태에 있을 때, 이 섹션의 규칙을 적용한다.

webkitdirectory 속성은 사용자가 파일 또는 파일들 대신 디렉터리를 선택할 수 있도록 허용하는지 여부를 나타내는 불리언 속성이다. 지정된 경우, 디렉터리 선택 시 해당 디렉터리를 상위로 하는 모든 파일이 선택된 것과 동일하게 동작한다. 또한, 각 webkitRelativePath 속성은 File 객체의 상대 경로로, 선택된 디렉터리부터 파일까지의 경로를 포함한다.

다음과 같은 디렉터리 구조가 있다고 가정한다:
documents/
  to_upload/
    a/
      b/
        1.txt
        2.txt
      3.txt
  not_uploaded.txt

to_upload 디렉터리를 선택한 경우, files 컬렉션에는 다음이 포함된다:

note: 사용자 에이전트는 선택 작업 중 계층적 데이터를 디렉터리로 표현할 수 있다. 예를 들어, 네이티브 파일 시스템을 직접 노출하지 않는 장치에서는 사진 앨범을 "image/*"accept 속성에 지정된 경우 디렉터리로 표시할 수 있다.

webkitRelativePath 속성을 디렉터리 선택 후 input 요소에서 검사하는 예:
<input id=b type=file webkitdirectory>
document.querySelector('#b').addEventListener('change', e => {
  for (file entry of e.target.files) {
    console.log(file.name, file.webkitRelativePath);
  }
});

webkitEntries IDL 속성은 스크립트가 선택된 항목에 접근할 수 있도록 한다. 이 속성에 접근할 때, 적용된다면 현재 선택된 파일(디렉터리 포함)들을 나타내는 FileSystemEntry 객체 배열을 반환해야 한다. 적용되지 않으면 null을 반환해야 한다.

webkitEntries를 사용하여 항목을 열거하는 예:
<input id=a type=file multiple>
document.querySelector('#a').addEventListener('change', e => {
  for (const entry of e.target.webkitEntries) {
    handleEntry(entry);
  }
});
상호운용성: Chrome에서는 webkitEntries 속성이 드래그 앤 드롭 작업의 결과로만 채워진다. 요소를 클릭할 때는 채워지지 않는다. 항상 채워지도록 수정해야 할까?
상호운용성: Chrome에서는 webkitdirectory 속성이 HTMLInputElement에 지정된 경우, webkitEntries 속성이 채워지지 않는다. 대신 files 컬렉션과 webkitRelativePath 속성을 사용해 디렉터리 구조를 재구성해야 한다. 항상 채워지도록 수정해야 할까?

6. HTML: 드래그 앤 드롭

편집: 이 섹션은 완성되면 [HTML]에 병합되어야 합니다.

드래그 앤 드롭 작업 중에는 파일디렉터리 항목이 항목에 연결됩니다. 각 항목루트 디렉터리의 멤버이며, 해당 드래그 데이터 저장소에 고유합니다.

또한, 각 디렉터리 항목은 드래그 데이터 저장소 항목 리스트에서 kindFile인 항목으로 표현됩니다. getAsFile() 로 접근할 경우 0 바이트 길이의 File 이 반환됩니다.

note: 사용자 에이전트는 드래그 앤 드롭 작업 중에 계층적 데이터를 파일과 디렉터리로 표현할 수 있습니다. 예를 들어, 앨범 메타데이터와 트랙 블롭이 별도의 테이블에 저장된 관계형 데이터베이스의 오디오 데이터를 미디어 플레이어에서 드래그하면 스크립트에서는 디렉터리와 파일로 노출될 수 있습니다.

partial interface DataTransferItem {
    FileSystemEntry? webkitGetAsEntry();
};

webkitGetAsEntry() 메서드 단계:

  1. storethisDataTransfer 객체의 드래그 데이터 저장소로 한다.

  2. store드래그 데이터 저장소 모드읽기/쓰기 모드 또는 읽기 전용 모드가 아니면, null을 반환하고 중단한다.

  3. itemstore드래그 데이터 저장소 항목 리스트에서 this가 나타내는 항목으로 한다.

  4. itemkindFile이 아니면 null을 반환하고 중단한다.

  5. 항목을 나타내는 새로운 FileSystemEntry 객체를 반환한다.

파일과 디렉터리의 드래그 앤 드롭 처리 예시:
elem.addEventListener('dragover', e => {
  // 네비게이션 방지.
  e.preventDefault();
});
elem.addEventListener('drop', e => {
  // 네비게이션 방지.
  e.preventDefault();

  // 모든 항목 처리.
  for (const item of e.dataTransfer.items) {
    // 파일/디렉터리 항목의 kind는 'file'.
    if (item.kind === 'file') {
      const entry = item.webkitGetAsEntry();
      handleEntry(entry);
    }
  }
});

7. 파일 및 디렉터리

웹 호환성: 기존 TypeMismatchError 는 대부분의 명세에서 TypeError 로 대체되었지만 이름이 다릅니다. 여기서도 바꿔도 호환성에 문제가 없을까요?
callback ErrorCallback = undefined (DOMException err);

ErrorCallback 함수는 비동기적으로 오류를 반환할 수 있는 동작에 사용됩니다.

태스크 소스가 아래 단계에서 큐잉된 태스크에 대해 정의되어 있지 않습니다. Chromium 기반 브라우저는 다음을 사용하는 것으로 보입니다:

7.1. FileSystemEntry 인터페이스

[Exposed=Window]
interface FileSystemEntry {
    readonly attribute boolean isFile;
    readonly attribute boolean isDirectory;
    readonly attribute USVString name;
    readonly attribute USVString fullPath;
    readonly attribute FileSystem filesystem;

    undefined getParent(optional FileSystemEntryCallback successCallback,
                   optional ErrorCallback errorCallback);
};

FileSystemEntry 는 연관된 항목을 가집니다.

isFile getter 단계는 this파일 항목이면 true, 아니면 false를 반환합니다.

isDirectory getter 단계는 this디렉터리 항목이면 true, 아니면 false를 반환합니다.

name getter 단계는 thisname을 반환합니다.

fullPath getter 단계는 thisfull path를 반환합니다.

filesystem getter 단계는 thisfile system을 반환합니다.

getParent(successCallback, errorCallback) 메서드 단계:

  1. 병렬로 다음 단계를 실행한다:

    1. path상대 경로 해석으로 thisfull path와 '..'을 사용한 결과로 한다.

    2. item경로 평가thisrootpath를 사용한 결과로 한다.

    3. item이 실패라면 태스크 큐에 추가하여 콜백 함수 호출errorCallback(있다면)과 « 새로 생성된 "NotFoundError" DOMException »와 "report"를 호출하고, 이 단계를 중단한다.

    4. entryitemnamename으로, pathfull path로 하는 새로운 디렉터리 항목으로 한다.

    5. 태스크 큐에 추가하여 콜백 함수 호출successCallback과 « FileSystemDirectoryEntry 객체(연관된 entry) »와 "report"를 호출한다.

note: FileSystemEntry 생성 이후 디스크의 파일이 변경되었을 때 오류가 발생할 수 있습니다.

항목 처리 예시:
function handleEntry(entry) {
  console.log('name: ' + entry.name);
  console.log('path: ' + entry.fullPath);
  if (entry.isFile) {
    console.log('... 파일입니다');
  } else if (entry.isDirectory) {
    console.log('... 디렉터리입니다');
  }
}
getParent()Promise [ECMA-262]와 함께 사용하는 헬퍼 함수 예시:
function getParentAsPromise(entry) {
  return new Promise((resolve, reject) => {
    entry.getParent(resolve, reject);
  });
}

7.2. FileSystemDirectoryEntry 인터페이스

[Exposed=Window]
interface FileSystemDirectoryEntry : FileSystemEntry {
    FileSystemDirectoryReader createReader();
    undefined getFile(optional USVString? path,
                 optional FileSystemFlags options = {},
                 optional FileSystemEntryCallback successCallback,
                 optional ErrorCallback errorCallback);
    undefined getDirectory(optional USVString? path,
                      optional FileSystemFlags options = {},
                      optional FileSystemEntryCallback successCallback,
                      optional ErrorCallback errorCallback);
};

dictionary FileSystemFlags {
    boolean create = false;
    boolean exclusive = false;
};

callback FileSystemEntryCallback = undefined (FileSystemEntry entry);

note: FileSystemFlagscreate 멤버와 연관된 동작은 기존 구현과의 호환성을 위해 포함되어 있지만, 해당 플래그가 지정되어도 유용한 동작은 없습니다. 마찬가지로 exclusive 멤버는 명시적으로 참조되지 않지만, getter가 있는 객체가 전달된 경우 스크립트에서 바인딩 동작을 관찰할 수 있습니다.

FileSystemDirectoryEntry의 연관 항목디렉터리 항목입니다.

createReader() 메서드 단계:

  1. 연관된 디렉터리 항목과 연결된 새 FileSystemDirectoryReader 객체를 반환한다.

getFile(path, options, successCallback, errorCallback) 메서드 단계:

  1. 병렬로 다음 단계를 실행한다:

    1. path가 undefined 또는 null이면 path를 빈 문자열로 한다.

    2. path유효한 경로가 아니면, 태스크 큐에 추가하여 콜백 함수 호출errorCallback(있다면)과 « 새로 생성된 "TypeMismatchError" DOMException »와 "report"를 호출하고, 이 단계를 중단한다.

    3. optionscreate 멤버가 true이면, 태스크 큐에 추가하여 콜백 함수 호출errorCallback(있다면)과 « 새로 생성된 "SecurityError" DOMException » 와 "report"를 호출하고, 이 단계를 중단한다.

    4. path상대 경로 해석으로 thisfull pathpath를 사용한 결과로 한다.

    5. item경로 평가thisrootpath를 사용한 결과로 한다.

    6. item이 실패라면 태스크 큐에 추가하여 콜백 함수 호출errorCallback(있다면)과 « 새로 생성된 "NotFoundError" DOMException »와 "report"를 호출하고, 이 단계를 중단한다.

    7. item파일이 아니면, 태스크 큐에 추가하여 콜백 함수 호출errorCallback(있다면)과 « 새로 생성된 "TypeMismatchError" DOMException »와 "report"를 호출하고, 이 단계를 중단한다.

    8. entryitemnamename으로, pathfull path로 하는 새로운 파일 항목으로 한다.

    9. 태스크 큐에 추가하여 콜백 함수 호출successCallback(있다면)과 « FileSystemFileEntry 객체(연관된 entry) »와 "report"를 호출한다.

getDirectory(path, options, successCallback, errorCallback) 메서드 단계:

  1. 병렬로 다음 단계를 실행한다:

    1. path가 undefined 또는 null이면 path를 빈 문자열로 한다.

    2. path유효한 경로가 아니면, 태스크 큐에 추가하여 콜백 함수 호출errorCallback(있다면)과 « 새로 생성된 "TypeMismatchError" DOMException »와 "report"를 호출하고, 이 단계를 중단한다.

    3. optionscreate 멤버가 true이면, 태스크 큐에 추가하여 콜백 함수 호출errorCallback(있다면)과 « 새로 생성된 "SecurityError" DOMException » 와 "report"를 호출하고, 이 단계를 중단한다.

    4. path상대 경로 해석으로 thisfull pathpath를 사용한 결과로 한다.

    5. item경로 평가thisrootpath를 사용한 결과로 한다.

    6. item이 실패라면 태스크 큐에 추가하여 콜백 함수 호출errorCallback(있다면)과 « 새로 생성된 "NotFoundError" DOMException »와 "report"를 호출하고, 이 단계를 중단한다.

    7. item디렉터리가 아니면, 콜백 함수 호출errorCallback(있다면)과 « 새로 생성된 "TypeMismatchError" DOMException »와 "report"를 호출하고, 이 단계를 중단한다.

    8. entryitemnamename으로, pathfull path로 하는 새로운 디렉터리 항목으로 한다.

    9. 태스크 큐에 추가하여 콜백 함수 호출successCallback(있다면)과 « FileSystemDirectoryEntry 객체(연관된 entry) »와 "report"를 호출한다.

getFile()getDirectory()Promise [ECMA-262]와 함께 사용하는 헬퍼 함수 예시:
function getFileAsPromise(entry, path) {
  return new Promise((resolve, reject) => {
    entry.getFile(path, {}, resolve, reject);
  });
}
function getDirectoryAsPromise(entry, path) {
  return new Promise((resolve, reject) => {
    entry.getDirectory(path, {}, resolve, reject);
  });
}

7.3. FileSystemDirectoryReader 인터페이스

[Exposed=Window]
interface FileSystemDirectoryReader {
    undefined readEntries(FileSystemEntriesCallback successCallback,
                     optional ErrorCallback errorCallback);
};
callback FileSystemEntriesCallback = undefined (sequence<FileSystemEntry> entries);
FileSystemDirectoryReader 는 연관된 entry (디렉터리 항목), 연관된 directory (초기값 null), reading flag (초기값 false), done flag (초기값 false), reader error (초기값 null)을 가진다.

readEntries(successCallback, errorCallback) 메서드 단계:

  1. thisreading flag가 true이면, 태스크 큐에 추가하여 콜백 함수 호출errorCallback과 « 새로 생성된 "InvalidStateError" DOMException »와 "report"를 호출하고, 이 단계를 중단한다.

  2. thisreader error가 null이 아니면, 태스크 큐에 추가하여 콜백 함수 호출errorCallback(있다면)과 « reader error »와 "report"를 호출하고, 이 단계를 중단한다.

  3. thisdone flag가 true이면, 태스크 큐에 추가하여 콜백 함수 호출successCallback과 빈 리스트와 "report"를 호출하고, 이 단계를 중단한다.

  4. thisreading flag를 true로 설정한다.

  5. 병렬로 다음 단계를 실행한다:

    1. thisdirectory가 null이면:

      1. dir경로 평가thisentryrootfull path를 사용한 결과로 한다.

      2. dir이 실패라면:

        1. 태스크 큐에 추가하여 다음을 수행한다:

          1. error를 새로 생성된 "NotFoundError" DOMException로 한다.

          2. thisreader errorerror로 설정한다.

          3. thisreading flag를 false로 설정한다.

          4. 콜백 함수 호출 errorCallback(있다면)과 « error » 와 "report"를 호출한다.

        2. 이 단계를 중단한다.

      3. thisdirectorydir로 설정한다.

    2. entriesthisdirectory에서 아직 이 FileSystemDirectoryReader에 의해 반환되지 않은 멤버 중 일부(0개 이상)로 한다.

    3. 이전 단계가 실패했다면(예: 디렉터리가 삭제되었거나 권한이 거부된 경우):

      1. 태스크 큐에 추가하여 다음을 수행한다:

        1. error를 적절한 DOMException으로 한다.

        2. thisreader errorerror로 설정한다.

        3. thisreading flag를 false로 설정한다.

        4. 콜백 함수 호출 errorCallback(있다면)과 « error »와 "report"를 호출한다.

      2. 이 단계를 중단한다.

    4. 태스크 큐에 추가하여 다음을 수행한다:

      1. entries가 비어 있으면 thisdone flag를 true로 설정한다.

      2. thisreading flag를 false로 설정한다.

      3. 콜백 함수 호출 successCallback과 « entries »와 "report"를 호출한다.

참고: reading flag의 사용으로 위 병렬 단계가 동시에 실행되는 것을 방지합니다. 별도의 병렬 큐 지정이 필요하지 않습니다.

디렉터리 항목 나열 예시:
const reader = dirEntry.createReader();
const doBatch = () => {

  // 배치 읽기.
  reader.readEntries(entries => {

    // 완료?
    if (entries.length === 0) {
      return;
    }

    // 배치 처리.
    entries.forEach(handleEntry);

    // 다음 배치 읽기.
    doBatch();

  }, error => console.warn(error));
};

// 읽기 시작
doBatch();
FileSystemDirectoryReaderPromise [ECMA-262]와 함께 사용하는 헬퍼 함수 예시:
function getEntriesAsPromise(dirEntry) {
  return new Promise((resolve, reject) => {
    const result = [];
    const reader = dirEntry.createReader();
    const doBatch = () => {
      reader.readEntries(entries => {
        if (entries.length > 0) {
          entries.forEach(e => result.push(e));
          doBatch();
        } else { 
          resolve(result);
        }
      }, reject);
    };
    doBatch();
  });
}
FileSystemDirectoryReaderAsyncIterators [ECMA-262]와 함께 사용하는 헬퍼 함수 예시:
async function* getEntriesAsAsyncIterator(dirEntry) {
  const reader = dirEntry.createReader();
  const getNextBatch = () => new Promise((resolve, reject) => {
    reader.readEntries(resolve, reject);
  });

  let entries;
  do {
    entries = await getNextBatch();
    for (const entry of entries) {
      yield entry;
    }
  } while (entries.length > 0);
}

이렇게 하면 for-await-of를 사용해 디렉터리 트리를 순서대로 비동기적으로 탐색할 수 있습니다:

async function show(entry) {
  console.log(entry.fullPath);
  if (entry.isDirectory) {
    for await (const e of getEntriesAsAsyncIterator(entry)) {
      await show(e);
    }
  }
}

7.4. FileSystemFileEntry 인터페이스

[Exposed=Window]
interface FileSystemFileEntry : FileSystemEntry {
    undefined file(FileCallback successCallback,
              optional ErrorCallback errorCallback);
};
callback FileCallback = undefined (File file);

FileSystemFileEntry의 연관 항목파일 항목입니다.

file(successCallback, errorCallback) 메서드 단계:

  1. 병렬로 다음 단계를 실행한다:

    1. item경로 평가thisrootfull path를 사용한 결과로 한다.

    2. item이 실패라면, 태스크 큐에 추가하여 콜백 함수 호출errorCallback(있다면)과 « 새로 생성된 "NotFoundError" DOMException »와 "report"를 호출하고, 이 단계를 중단한다.

    3. item디렉터리이면, 태스크 큐에 추가하여 콜백 함수 호출errorCallback(있다면)과 « 새로 생성된 "TypeMismatchError" DOMException »와 "report"를 호출하고, 이 단계를 중단한다.

    4. 태스크 큐에 추가하여 콜백 함수 호출successCallback과 « File 객체(item에 해당) »와 "report"를 호출한다.

FileReader를 사용해 드롭된 파일의 내용을 읽는 예시:
function readFileEntry(entry) {
  entry.file(file => {
    const reader = new FileReader();
    reader.readAsText(file);
    reader.onerror = error => console.warn(error);
    reader.onload = () => {
      console.log(reader.result);
    };
  }, error => console.warn(error));
}
file()Promise [ECMA-262]와 함께 사용하는 헬퍼 함수 예시:
function fileAsPromise(entry) {
  return new Promise((resolve, reject) => {
    entry.file(resolve, reject);
  });
}

7.5. FileSystem 인터페이스

[Exposed=Window]
interface FileSystem {
    readonly attribute USVString name;
    readonly attribute FileSystemDirectoryEntry root;
};

FileSystem 는 연관된 파일 시스템을 가집니다.

name getter 단계는 thisname을 반환합니다.

root getter 단계는 FileSystemDirectoryEntry 객체(연관된 thisroot)를 반환합니다.

8. 감사의 글

이 명세서는 [file-system-api]에서 Eric Uhrhane이 작성한 작업에 크게 기반하고 있으며, 그 작업에서 FileSystemEntry 타입을 도입하였습니다.

이 문서 작성에 사용된 명세 저작 도구 Bikeshed를 만들고 유지 관리한 Tab Atkins, Jr.에게 감사드립니다.

그리고 Ali Alabbas, Philip Jägenstedt, Marijn Kruisselbrink, Olli Pettay, 그리고 Kent Tamura 등에게 제안, 리뷰, 기타 피드백을 주셔서 감사합니다.

적합성

문서 규칙

적합성 요구 사항은 설명적 단언과 RFC 2119 용어의 조합으로 표현됩니다. 본 문서의 규범적 부분에서 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, “OPTIONAL” 등의 핵심 단어는 RFC 2119에서 정의된 대로 해석해야 합니다. 그러나 가독성을 위해 이 명세에서는 이러한 단어가 모두 대문자로 나타나지 않습니다.

이 명세의 모든 텍스트는 규범적이며, 명시적으로 비규범적임을 표시한 섹션, 예시, 주석만 예외입니다. [RFC2119]

이 명세의 예제는 “예를 들어”라는 말로 시작하거나, class="example"와 같이 규범적 텍스트와 구분되어 있습니다:

이것은 참고용 예제의 예시입니다.

참고용 주석은 “참고”라는 말로 시작하며, class="note"와 같이 규범적 텍스트와 구분되어 있습니다:

참고: 이것은 참고용 주석입니다.

색인

이 명세서에서 정의된 용어

참조로 정의된 용어

참고문헌

규범적 참고문헌

[FileAPI]
Marijn Kruisselbrink. File API. URL: https://w3c.github.io/FileAPI/
[HTML]
Anne van Kesteren; et al. HTML 표준. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준. 현행 표준. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. RFC에서 요구 사항 수준을 나타내기 위한 핵심 단어. 1997년 3월. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. 현행 표준. URL: https://webidl.spec.whatwg.org/

참고용 참고문헌

[ECMA-262]
ECMAScript 언어 명세. URL: https://tc39.es/ecma262/multipage/
[FILE-SYSTEM-API]
Eric Uhrhane. File API: 디렉터리 및 시스템. URL: https://dev.w3.org/2009/dap/file-system/file-dir-sys.html

IDL 색인

partial interface File {
    readonly attribute USVString webkitRelativePath;
};

partial interface HTMLInputElement {
    attribute boolean webkitdirectory;
    readonly attribute FrozenArray<FileSystemEntry> webkitEntries;
};

partial interface DataTransferItem {
    FileSystemEntry? webkitGetAsEntry();
};

callback ErrorCallback = undefined (DOMException err);

[Exposed=Window]
interface FileSystemEntry {
    readonly attribute boolean isFile;
    readonly attribute boolean isDirectory;
    readonly attribute USVString name;
    readonly attribute USVString fullPath;
    readonly attribute FileSystem filesystem;

    undefined getParent(optional FileSystemEntryCallback successCallback,
                   optional ErrorCallback errorCallback);
};

[Exposed=Window]
interface FileSystemDirectoryEntry : FileSystemEntry {
    FileSystemDirectoryReader createReader();
    undefined getFile(optional USVString? path,
                 optional FileSystemFlags options = {},
                 optional FileSystemEntryCallback successCallback,
                 optional ErrorCallback errorCallback);
    undefined getDirectory(optional USVString? path,
                      optional FileSystemFlags options = {},
                      optional FileSystemEntryCallback successCallback,
                      optional ErrorCallback errorCallback);
};

dictionary FileSystemFlags {
    boolean create = false;
    boolean exclusive = false;
};

callback FileSystemEntryCallback = undefined (FileSystemEntry entry);

[Exposed=Window]
interface FileSystemDirectoryReader {
    undefined readEntries(FileSystemEntriesCallback successCallback,
                     optional ErrorCallback errorCallback);
};
callback FileSystemEntriesCallback = undefined (sequence<FileSystemEntry> entries);

[Exposed=Window]
interface FileSystemFileEntry : FileSystemEntry {
    undefined file(FileCallback successCallback,
              optional ErrorCallback errorCallback);
};
callback FileCallback = undefined (File file);

[Exposed=Window]
interface FileSystem {
    readonly attribute USVString name;
    readonly attribute FileSystemDirectoryEntry root;
};

이슈 색인

편집: directoryfile의 특수 타입으로 정의하여 [HTML]에서 최소한의 변경만 필요하도록 해야 할까요?
편집: 이 섹션은 완성되면 [FileAPI]에 병합되어야 합니다.
편집: 이 섹션은 완성되면 [HTML]에 병합되어야 합니다. 엔트리 리스트 생성 단계 등은 webkitRelativePath 속성을 포함하도록 확장되어야 합니다.
상호운용성: Chrome에서는 webkitEntries 속성이 드래그 앤 드롭 작업의 결과로만 채워지고, 요소를 클릭할 때는 채워지지 않습니다. 항상 채워지도록 수정해야 할까요?
상호운용성: Chrome에서는 webkitdirectory 속성이 HTMLInputElement에 지정된 경우, webkitEntries 속성이 채워지지 않습니다. 대신 files 컬렉션과 webkitRelativePath 속성을 사용해 디렉터리 구조를 재구성해야 합니다. 항상 채워지도록 수정해야 할까요?
편집: 이 섹션은 완성되면 [HTML]에 병합되어야 합니다.
웹 호환성: 기존 TypeMismatchError 는 대부분의 명세에서 TypeError 로 대체되었지만 이름이 다릅니다. 여기서도 바꿔도 호환성에 문제가 없을까요?
태스크 소스가 아래 단계에서 큐잉된 태스크에 대해 정의되어 있지 않습니다. Chromium 기반 브라우저는 다음을 사용하는 것으로 보입니다:
MDN

DataTransferItem/webkitGetAsEntry

In all current engines.

Firefox50+Safari11.1+Chrome13+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for AndroidNoneiOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

File/webkitRelativePath

In all current engines.

Firefox50+Safari11.1+Chrome13+
Opera?Edge79+
Edge (Legacy)13+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystem/name

In all current engines.

Firefox50+Safari11.1+Chrome7+
Opera?Edge79+
Edge (Legacy)18IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystem/root

In all current engines.

Firefox50+Safari11.1+Chrome7+
Opera?Edge79+
Edge (Legacy)18IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystem

In all current engines.

Firefox50+Safari11.1+Chrome7+
Opera?Edge79+
Edge (Legacy)18IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemDirectoryEntry/createReader

In all current engines.

Firefox50+Safari11.1+Chrome13+
OperaNoneEdge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemDirectoryEntry/getDirectory

In all current engines.

Firefox50+Safari11.1+Chrome8+
OperaNoneEdge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemDirectoryEntry/getFile

In all current engines.

Firefox50+Safari11.1+Chrome8+
OperaNoneEdge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemDirectoryEntry

In all current engines.

Firefox50+Safari11.1+Chrome8+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemDirectoryReader/readEntries

In all current engines.

Firefox50+Safari11.1+Chrome8+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemDirectoryReader

In all current engines.

Firefox50+Safari11.1+Chrome8+
Opera?Edge79+
Edge (Legacy)18IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemEntry/filesystem

In all current engines.

Firefox50+Safari11.1+Chrome8+
OperaNoneEdge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemEntry/fullPath

In all current engines.

Firefox50+Safari11.1+Chrome8+
OperaNoneEdge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemEntry/getParent

In all current engines.

Firefox52+Safari11.1+Chrome8+
OperaNoneEdge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemEntry/isDirectory

In all current engines.

Firefox50+Safari11.1+Chrome8+
OperaNoneEdge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemEntry/isFile

In all current engines.

Firefox50+Safari11.1+Chrome8+
OperaNoneEdge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemEntry/name

In all current engines.

Firefox50+Safari11.1+Chrome8+
OperaNoneEdge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemEntry

In all current engines.

Firefox50+Safari11.1+Chrome8+
OperaNoneEdge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemFileEntry/file

In all current engines.

Firefox50+Safari11.1+Chrome8+
OperaNoneEdge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

FileSystemFileEntry

In all current engines.

Firefox50+Safari11.1+Chrome8+
OperaNoneEdge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

HTMLInputElement/webkitdirectory

In all current engines.

Firefox50+Safari11.1+Chrome7+
Opera?Edge79+
Edge (Legacy)13+IENone
Firefox for AndroidNoneiOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

HTMLInputElement/webkitEntries

In all current engines.

Firefox50+Safari11.1+Chrome22+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for AndroidNoneiOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?