1. 소개
이 섹션은 규범적이지 않습니다.
이 API는 개발자가 사용자의 디바이스에 있는 (웹이 아닌) 다른 앱과 디바이스의 파일 시스템을 통해 상호작용하는 강력한 앱을 구축할 수 있도록 합니다. 이 기능이 기대되는 대표적인 응용 프로그램으로는 IDE, 사진 및 비디오 편집기, 텍스트 편집기 등이 있습니다. 사용자가 웹 앱에 접근 권한을 부여한 후, 이 API를 통해 앱은 사용자의 디바이스에 있는 파일 및 폴더를 직접 읽거나 변경사항을 저장할 수 있습니다. 파일 읽기 및 쓰기 기능을 넘어서, 이 API는 디렉터리를 열어 그 내용을 나열하는 기능도 제공합니다. 또한, 웹 앱은 이 API를 이용해 접근 권한이 부여된 파일 및 디렉터리의 참조를 저장할 수 있으므로, 사용자가 동일한 파일을 다시 선택하지 않아도 웹 앱이 나중에 동일한 콘텐츠에 다시 접근할 수 있습니다.
이 API는 사용자의 상호작용이 파일 및 디렉터리 선택기 대화상자를 통해 이루어진다는 점에서 <input type=file>
및 <input type=file webkitdirectory>
[entries-api]
와 유사합니다.
하지만 이 API는 순수하게 자바스크립트 API이며, 폼 또는 input 요소와 통합되지 않습니다.
이 API는 [FS]의 API를 확장하며, 버킷 파일 시스템을 정의합니다. 이를 통해 웹사이트는 사용자에게 먼저 접근 권한을 요청하지 않고도 접근할 수 있습니다.
2. 파일 및 디렉터리
2.1. 개념
유효한 접미사 코드 포인트는 코드 포인트 중 ASCII 영숫자, U+002B (+), 또는 U+002E (.)인 값입니다.
참고: 이러한 코드 포인트는 대부분의 기존 파일 형식을 지원하기 위해 선택되었습니다. 대부분의 파일
확장자는 순수하게 영숫자이지만, .tar.gz 와 같은 복합 확장자나 C++ 소스 파일의 .c++ 와 같은 확장자도 자주 사용되므로 +와 .을
허용된 코드 포인트에 포함했습니다.
2.2. 권한
"file-system" 강력한
기능의
권한 관련 알고리즘과 타입은 다음과 같이 정의됩니다:
- permission descriptor type
-
FileSystemPermissionDescriptor는 다음과 같이 정의됩니다:enum {FileSystemPermissionMode ,"read" };"readwrite" dictionary :FileSystemPermissionDescriptor PermissionDescriptor {required FileSystemHandle ;handle FileSystemPermissionMode = "read"; };mode - permission state constraints
-
FileSystemPermissionDescriptordesc에 대한 permission state constraints를 결정하려면, 다음 절차를 따르세요:
이러한 검사가 엔트리에 더 이상 연결되지 않도록 해야 합니다. [whatwg/fs Issue #101]
- permission request algorithm
-
FileSystemPermissionDescriptordesc와PermissionStatusstatus가 주어졌을 때, 다음 단계를 실행하세요:-
desc 및 status에 대해 기본 권한 쿼리 알고리즘을 실행합니다.
-
global을 settings의 global object로 둡니다.
-
global이
Window가 아니면, "SecurityError"DOMException을 throw 합니다. -
global에 transient activation이 없으면, "
SecurityError"DOMException을 throw 합니다. -
settings의 origin 이 settings의 top-level origin과 동일 출처가 아니면, "
SecurityError"DOMException을 throw 합니다. -
desc를 사용하기 위해 권한을 요청합니다.
-
desc 및 status에 대해 기본 권한 쿼리 알고리즘을 실행합니다.
이상적으로는 이 사용자 활성화 요구사항이 상위 수준에서 정의되는 것이 더 좋겠습니다. [WICG/permissions-request Issue #2]
-
FileSystemHandle
handle과 FileSystemPermissionMode
mode를 받아 파일 시스템 권한을 쿼리하는 방법은 다음과 같습니다:
-
desc를
FileSystemPermissionDescriptor로 둡니다. -
desc["
name"]를 "file-system"으로 설정합니다. -
desc["
handle"]에 handle을 설정합니다. -
desc["
mode"]에 mode를 설정합니다. -
desc의 권한 상태를 반환합니다.
FileSystemHandle
handle과 FileSystemPermissionMode
mode를 받아 파일 시스템 권한을 요청하는 방법은 다음과 같습니다:
-
desc를
FileSystemPermissionDescriptor로 둡니다. -
desc["
name"]를 "file-system"으로 설정합니다. -
desc["
handle"]에 handle을 설정합니다. -
desc["
mode"]에 mode를 설정합니다. -
desc에 대해 PermissionStatus 생성의 결과를 status에 할당합니다.
-
"
file-system" 기능, desc 및 status에 대해 permission request algorithm을 실행합니다. -
desc의 권한 상태를 반환합니다.
현재 FileSystemPermissionMode
값은
"read"
또는 "readwrite"
만 가능합니다. 앞으로는 쓰기 전용 핸들 지원을 위해 "write" 모드를 추가할 수도 있습니다. [Issue #119]
2.3. FileSystemHandle
인터페이스
dictionary {FileSystemHandlePermissionDescriptor FileSystemPermissionMode = "read"; }; [mode Exposed =(Window ,Worker ),SecureContext ,Serializable ]partial interface FileSystemHandle {Promise <PermissionState >queryPermission (optional FileSystemHandlePermissionDescriptor = {});descriptor Promise <PermissionState >requestPermission (optional FileSystemHandlePermissionDescriptor = {}); };descriptor
2.3.1. queryPermission()
메서드
- status = await handle .
queryPermission({mode: "read" })- status = await handle .
queryPermission()- status = (await navigator.
permissions.query({name: "file-system",handle: handle })).state - status = await handle .
-
이 핸들(handle)의 읽기 권한 현재 상태를 조회합니다. 만약 이 호출이 "
prompt" 를 반환하면, 웹사이트는 해당 핸들에 대한 어떤 작업을 수행하기 전에requestPermission()을 호출해야 합니다. 만약 "denied" 를 반환하면 모든 연산은 거부됩니다.보통 로컬 파일 시스템 핸들 생성기들이 반환하는 핸들은 처음에는 읽기 권한 상태에 대해 "
granted" 를 반환하지만, 사용자가 권한을 취소한 경우를 제외하고는 IndexedDB에서 가져온 핸들은 "prompt" 를 반환할 가능성도 있습니다. - status = await handle .
queryPermission({mode: "readwrite" })- status = (await navigator.
permissions.query({name: "file-system",handle: handle,mode: "readwrite" }).state - status = (await navigator.
-
이 핸들(handle)의 쓰기 권한 현재 상태를 조회합니다. 만약 이것이 "
prompt" 를 반환하면, 파일이나 디렉터리를 수정하려고 시도할 때 사용자 활성화가 필요하며 사용자에게 확인 프롬프트가 표시됩니다. 그러나 이 핸들의 읽기 권한 상태도 "prompt" 인 경우에는 웹사이트가requestPermission()을 호출해야 합니다. 읽기 접근에 대해서는 파일이나 디렉터리에서 읽기를 시도할 때 자동으로 프롬프트가 발생하지 않습니다.
권한 API의 query()
메서드와의 통합은 아직 Chrome에 구현되어 있지 않습니다.
queryPermission(descriptor)
메서드는 호출되었을 때 다음 단계를 실행해야 합니다:
2.3.2. requestPermission()
메서드
- status = await handle .
requestPermission({mode: "read" })- status = await handle .
requestPermission() - status = await handle .
-
이 핸들(handle)의 읽기 권한 상태가 "
prompt" 이외의 값이면, 이 호출은 그 상태를 그대로 반환합니다. 만약 상태가 "prompt" 인 경우에는 사용자 활성화가 필요하며 사용자에게 확인 프롬프트가 표시됩니다. 이후 사용자의 응답에 따라 새로운 읽기 권한 상태가 반환됩니다. - status = await handle .
requestPermission({mode: "readwrite" }) -
이 핸들(handle)의 쓰기 권한 상태가 "
prompt" 이외의 값이면, 이 호출은 그 상태를 그대로 반환합니다. 만약 이 핸들의 읽기 권한 상태가 "denied" 라면, 이 상태를 반환합니다.그렇지 않다면 쓰기 권한의 상태가 "
prompt" 이며 이 경우 사용자에게 확인 프롬프트가 표시됩니다. 이후 사용자가 선택한 내용에 따라 새로운 쓰기 권한 상태가 반환됩니다.
requestPermission(descriptor)
메서드는 호출되었을 때 다음 단계를 실행해야 합니다:
3. 로컬 파일 시스템 접근
enum WellKnownDirectory {"desktop" ,"documents" ,"downloads" ,"music" ,"pictures" ,"videos" , };typedef (WellKnownDirectory or FileSystemHandle );StartInDirectory dictionary {FilePickerAcceptType USVString = "";description record <USVString , (USVString or sequence <USVString >)>; };accept dictionary {FilePickerOptions sequence <FilePickerAcceptType >;types boolean =excludeAcceptAllOption false ;DOMString ;id StartInDirectory ; };startIn dictionary :OpenFilePickerOptions FilePickerOptions {boolean =multiple false ; };dictionary :SaveFilePickerOptions FilePickerOptions {USVString ?; };suggestedName dictionary {DirectoryPickerOptions DOMString ;id StartInDirectory ;startIn FileSystemPermissionMode = "read"; }; [mode SecureContext ]partial interface Window {Promise <sequence <FileSystemFileHandle >>showOpenFilePicker (optional OpenFilePickerOptions = {});options Promise <FileSystemFileHandle >showSaveFilePicker (optional SaveFilePickerOptions = {});options Promise <FileSystemDirectoryHandle >showDirectoryPicker (optional DirectoryPickerOptions = {}); };options
showOpenFilePicker(),
showSaveFilePicker()
및 showDirectoryPicker()
메서드들은 합쳐서 로컬 파일 시스템 핸들 생성기들로 불립니다.
참고: 이 규격에서 "로컬 파일 시스템"이라 칭하는 것은 반드시 로컬 기기의 파일 시스템만을 의미하지 않습니다. 우리가 말하는 로컬 파일 시스템은 클라우드 제공자에 의해 백업될 수도 있습니다. 예를 들어 Chrome OS에서는 이 파일 선택기가 Google Drive의 파일 및 디렉터리도 선택할 수 있도록 합니다.
Chrome 버전 85 이전에서는, 이것이 일반적인 chooseFileSystemEntries 메서드로
구현되었습니다.
3.1. 로컬 파일 시스템 권한
프롬프트에서 로컬 파일 시스템 핸들 생성기들가 반환한 특정 파일들을 사용자가 선택했다는 사실은, 사용자
에이전트가 해당 파일들에 대해 웹사이트에 읽기 접근을 허용하려는 사용자의 의도로 간주해야 합니다. 따라서 로컬 파일 시스템 핸들 생성기들 중 하나가 반환하는 프라미스가 해결될 때,
permission state는 handle
이 반환된 핸들로 설정되고,
mode
가 "read"
로 설정되어 있으면 "granted"
여야 합니다.
또한 showSaveFilePicker
호출의 경우에는, permission state가 handle
을 반환된 핸들로 설정하고,
mode
가 "readwrite"
로 설정되어 있으면 "granted"
여야 합니다.
환경(environment)이 파일 선택기를 표시할 수 있는지 검증하려면 다음 단계를 실행합니다:
-
만약 environment의 origin이 opaque origin이면, "
SecurityError"DOMException로 거부된 프라미스를 반환합니다. -
만약 environment의 origin이 top-level origin과 동일 출처가 아니면, "
SecurityError"DOMException로 거부된 프라미스를 반환합니다. -
global를 environment의 global object로 둡니다.
-
만약 global이 transient activation을 가지고 있지 않다면, "
SecurityError"DOMException을 throw 합니다.
3.2. 파일 선택기 옵션
3.2.1. 허용된 파일 유형
showOpenFilePicker(options)
및 showSaveFilePicker(options)
메서드는 웹사이트가 파일 선택기가 사용자가 선택할 수 있도록 할 파일 유형을 지정할 수 있게 하는
FilePickerOptions
인수를 받아들입니다.
types
의 각 항목은 파일 선택기에 표시되는 파일을 필터링하기 위한 단일 사용자 선택 가능한 옵션을 지정합니다.
각 옵션은 선택적 description
과 여러 MIME 유형 및 확장자로 구성됩니다 (MIME 유형에서 확장자 목록으로의 매핑으로 지정). 설명이 제공되지 않으면 하나가 생성됩니다.
확장자는 "."으로 시작하고 유효한 접미사 코드 포인트만 포함하는 문자열이어야 합니다.
또한 확장자는 16 코드 포인트의 길이로 제한됩니다.
완전한 MIME 유형 외에도 "*"는 MIME 유형의 하위 유형으로 사용할 수 있으며, 예를 들어 "image/*"로 모든 이미지 형식을 일치시킬 수 있습니다.
웹사이트는 항상 각 옵션에 대해 MIME 유형과 파일 확장자를 모두 제공해야 합니다. 파일 확장자만을 사용하여 파일 유형을 설명하는 플랫폼에서는 사용자 에이전트가 확장자에 일치할 수 있으며, 확장자를 사용하지 않는 플랫폼에서는 사용자 에이전트가 MIME 유형에 일치할 수 있습니다.
기본적으로 파일 선택기는 사용자가 어떤 파일이든 선택할 수 있도록 필터를 적용하지 않는 옵션도 포함합니다. excludeAcceptAllOption
을 true로 설정하여
파일 선택기에 이 옵션을 포함하지 마십시오.
예를 들어, 다음 옵션은 사용자가 세 가지 다른 필터 중 하나를 선택할 수 있도록 합니다. 하나는 텍스트 파일(일반 텍스트 또는 HTML), 하나는 이미지, 그리고 세 번째는 필터를 적용하지 않고 사용자가 어떤 파일이든 선택할 수 있도록 합니다.
const options= { types: [ { description: 'Text Files' , accept: { 'text/plain' : [ '.txt' , '.text' ], 'text/html' : [ '.html' , '.htm' ] } }, { description: 'Images' , accept: { 'image/*' : [ '.png' , '.gif' , '.jpeg' , '.jpg' ] } }, ], };
반면에, 다음 예제는 사용자가 SVG 파일만 선택할 수 있도록 합니다. 대화 상자는 필터를 적용하지 않는 옵션을 표시하지 않습니다.
const options= { types: [ { accept: { 'image/svg+xml' : '.svg' } }, ], excludeAcceptAllOption: true };
FilePickerOptions
options가 주어지면 수락 유형을 처리하려면 다음 단계를 실행합니다:
-
accepts options를 설명과 필터로 구성된 빈 목록으로 둡니다.
-
options["
types"]의 각 type에 대해:-
type["
accept"]의 각 typeString → suffixes에 대해:-
parsedType를 typeString으로 MIME 유형을 파싱한 결과로 둡니다.
-
parsedType의 parameters가 비어 있지 않으면,
TypeError를 throw 합니다. -
suffixes가 문자열이면:
-
suffixes가 주어진 접미사를 검증합니다.
-
-
그렇지 않으면, suffixes의 각 suffix에 대해:
-
suffix가 주어진 접미사를 검증합니다.
-
-
-
filter를 이 단계로 둡니다. filename (문자열)과 type (MIME 유형)가 주어지면:
-
type["
accept"]의 각 typeString → suffixes에 대해: -
parsedType를 typeString으로 MIME 유형을 파싱한 결과로 둡니다.
-
false를 반환합니다.
-
-
description를 type["
description"]으로 둡니다. -
description가 빈 문자열이면, filter를 설명하는 사용자 이해 가능한 문자열로 description을 설정합니다.
-
(description, filter)를 accepts options에 추가합니다.
-
-
accepts options가 비어 있거나, options["
excludeAcceptAllOption"] 이false이면:-
description를 "all files"를 설명하는 사용자 이해 가능한 문자열로 둡니다.
-
filter를
true를 반환하는 알고리즘으로 둡니다. -
(description, filter)를 accepts options에 추가합니다.
-
-
-
accepts options를 반환합니다.
3.2.2. 시작 디렉터리
id
및 startIn
필드를 지정하여 파일 선택기가 열릴 디렉터리를 제안할 수 있습니다.
이러한 옵션이 지정되지 않으면, 사용자 에이전트는 마지막으로 파일이나 디렉터리를 선택한 디렉터리를 기억하며, 새로운 선택기는 해당 디렉터리에서 시작합니다. id
를 지정하면 사용자 에이전트는 다른 ID에 대해 다른 디렉터리를 기억할 수 있습니다
(사용자 에이전트는 제한된 수의 ID에 대해서만 디렉터리를 기억합니다).
// 이 ID에 대한 매핑이 존재하면, 이 디렉터리에서 시작합니다. // 그렇지 않으면, 이 ID에 대한 매핑이 생성되며, // 파일 선택기 호출의 결과 디렉터리에 매핑됩니다. const options= { id: 'foo' , };
startIn
을 FileSystemFileHandle
로 지정하면 대화 상자가 해당 파일의 부모 디렉터리에서 시작됩니다. 반면 FileSystemDirectoryHandle
을 전달하면 대화 상자가 전달된 디렉터리에서 시작됩니다. 명시적 id
가 또한 전달되더라도 이들은 우선합니다.
예를 들어, FileSystemDirectoryHandle
project_dir가 주어지면 다음은 해당 디렉터리에서 시작하는 파일 선택기를 표시합니다:
// 선택기는 |project_dir|의 디렉터리에서 열립니다. 'foo'가 유효한 매핑을 가지고 있는지 여부와 무관합니다. const options= { id: 'foo' , startIn: | project_dir| , };
id
및 startIn
필드는 선택기가 열릴 디렉터리만 제어합니다. 위의 예제에서는 선택기가 파일 선택기 작업을 완료한 후 id
'foo'가 project_dir과 동일한 디렉터리에 매핑된다고 가정할 수 없습니다.
startIn
을 WellKnownDirectory
로 지정하면 대화 상자가 해당 디렉터리에서 시작되며, 명시적 id
가 또한 전달되어 유효한 디렉터리에 대한 매핑이 있는 경우가 아니면 그렇습니다.
아래는 id
와
startIn
을 WellKnownDirectory
로 지정하는 예제입니다.
주어진 ID에 대한 기존 매핑이 존재하면 해당 매핑이 사용됩니다. 그렇지 않으면 WellKnownDirectory
에서 제안한 경로가 사용됩니다.
// ID 'foo'에 대해 처음 지정합니다. 이는 디렉터리에 매핑되지 않습니다. // 파일 선택기는 다운로드 디렉터리에서 열리도록 폴백됩니다. TODO: link this. const options= { id: 'foo' , // 매핑되지 않음. startIn: " downloads " , // 여기서 시작. }; // 나중에... // ID 'foo'는 매핑될 수도 있고 아닐 수도 있습니다. 예를 들어, 이 ID에 대한 매핑이 // 제거되었을 수 있습니다. const options= { id: 'foo' , // 매핑될 수도 있음. 그렇다면 여기서 시작. startIn: " downloads " , // 그렇지 않으면 여기서 시작. };
startIn
및 id
옵션은 Chrome 91에서 처음 도입되었습니다.
사용자 에이전트는 최근에 선택된 디렉터리 맵을 보유하며, 이는 맵 origins에서 경로 id 맵으로의 맵입니다.
경로 id 맵은 맵 유효한 경로 id에서 경로로의 맵입니다.
유효한 경로 id는 각 문자가 ASCII 알파벳숫자 또는 "_" 또는 "-"인 문자열입니다.
경로 id 맵이 제한 없이 증가하는 것을 방지하기 위해 사용자 에이전트는 최근에 선택된 디렉터리가 기억되는 수를 제한하는 메커니즘을 구현해야 합니다. 이는 예를 들어 가장 최근에 사용되지 않은 항목을 제거하는 것으로 수행할 수 있습니다. 사용자 에이전트는 경로 id 맵에 최소 16개의 항목을 저장할 수 있도록 해야 합니다.
WellKnownDirectory 열거형은 웹사이트가 여러 잘 알려진
디렉터리 중 하나를 선택할 수 있도록 합니다. 이 열거형의 다양한 값이 매핑되는 정확한 경로는 implementation-defined
이며, 경우에 따라 디스크 상에 실제 경로를 나타내지 않을 수도 있습니다.
다음 목록은 각 값의 의미를 설명하며, 다른 운영 체제에서 가능한 예제 경로를 제공합니다:
"desktop"-
사용자의 데스크톱 디렉터리(존재한다면). 예를 들어
C:\Documents and Settings\username\Desktop,/Users/username/Desktop, 또는/home/username/Desktop가 될 수 있습니다. "documents"-
사용자가 만든 문서가 일반적으로 저장되는 디렉터리. 예를 들어
C:\Documents and Settings\username\My Documents,/Users/username/Documents, 또는/home/username/Documents. "downloads"-
다운로드된 파일이 일반적으로 저장되는 디렉터리. 예를 들어
C:\Documents and Settings\username\Downloads,/Users/username/Downloads, 또는/home/username/Downloads. "music"-
오디오 파일이 일반적으로 저장되는 디렉터리. 예를 들어
C:\Documents and Settings\username\My Documents\My Music,/Users/username/Music, 또는/home/username/Music. "pictures"-
사진 및 기타 정지 이미지가 일반적으로 저장되는 디렉터리. 예를 들어
C:\Documents and Settings\username\My Documents\My Pictures,/Users/username/Pictures, 또는/home/username/Pictures. "videos"-
비디오/영화가 일반적으로 저장되는 디렉터리. 예를 들어
C:\Documents and Settings\username\My Documents\My Videos,/Users/username/Movies, 또는/home/username/Videos. -
origin을 environment의 origin으로 둡니다.
-
startIn이
FileSystemHandle이고 startIn이 버킷 파일 시스템에 있지 않은 경우: -
id가 비어 있지 않으면:
-
최근에 선택된 디렉터리 맵[origin] 존재하면:
-
path map을 최근에 선택된 디렉터리 맵[origin]으로 둡니다.
-
path map[id] 존재하면 path map[id]를 반환합니다.
-
-
-
startIn이
WellKnownDirectory이면:-
startIn의
WellKnownDirectory값에 해당하는 사용자 에이전트 정의 경로를 반환합니다.
-
-
id가 지정되지 않았거나 빈 문자열이면:
-
최근에 선택된 디렉터리 맵[origin] 존재하면:
-
path map을 최근에 선택된 디렉터리 맵[origin]으로 둡니다.
-
path map[""] 존재하면 path map[""]을 반환합니다.
-
-
-
사용자 에이전트 특정 방식으로 기본 경로를 반환합니다.
-
origin을 environment의 origin으로 둡니다.
-
최근에 선택된 디렉터리 맵[origin]이 존재하지 않으면, 최근에 선택된 디렉터리 맵[origin]을 빈 경로 id 맵으로 설정합니다.
-
id가 지정되지 않았으면 id를 빈 문자열로 둡니다.
-
최근에 선택된 디렉터리 맵[origin][id]를 로컬 파일 시스템에서 entry에 해당하는 경로로 설정합니다, 그러한 경로를 결정할 수 있는 경우.
- [ handle ] = await window .
showOpenFilePicker()- [ handle ] = await window .
showOpenFilePicker({multiple: false }) - [ handle ] = await window .
-
사용자가 단일 기존 파일을 선택할 수 있도록 하는 파일 선택기를 표시하며, 선택된 파일에 대한 핸들을 반환합니다.
- handles = await window .
showOpenFilePicker({multiple: true }) -
사용자가 여러 기존 파일을 선택할 수 있도록 하는 파일 선택기를 표시하며, 선택된 파일들에 대한 핸들을 반환합니다.
showOpenFilePicker()에 추가 옵션을 전달하여 웹사이트가 사용자가 선택할 파일 유형과 파일 선택기가 열릴 디렉터리를 나타낼 수 있습니다. 자세한 내용은 § 3.2 File picker options를 참조하십시오. -
accepts options를 options를 사용하여 수락 유형을 처리한 결과로 둡니다.
-
starting directory를 options["
id"], options["startIn"], 및 environment를 사용하여 선택기가 시작할 디렉터리를 결정한 결과로 둡니다. -
global을 environment의 global object로 둡니다.
-
environment가 파일 선택기를 표시할 수 있는지 확인합니다.
-
p를 새로운 프라미스로 둡니다.
-
다음 단계를 병렬로 실행합니다:
-
선택적으로, 이 알고리즘의 이전 실행이 종료될 때까지 기다립니다.
-
filePickerOptions를 빈 맵으로 둡니다.
-
filePickerOptions["multiple"]을 options["
multiple"]으로 설정합니다. -
dismissed를 null과 filePickerOptions로 WebDriver BiDi 파일 대화 상자가 열린 결과로 둡니다.
-
dismissed가 false이면:
-
사용자에게 파일을 선택하도록 요청하는 프롬프트를 표시합니다. filePickerOptions["multiple"]이 false이면 파일이 하나만 선택되어야 합니다; 그렇지 않으면 여러 개가 선택될 수 있습니다.
표시된 프롬프트는 표시된 파일 목록을 필터링하기 위해 accepts options 중 하나를 선택할 수 있도록 해야 합니다. 정확히 어떻게 구현되며, 이 프롬프트가 어떻게 보이는지는 implementation-defined입니다.
가능하다면 이 프롬프트는 starting directory를 표시하도록 시작해야 합니다.
-
사용자가 선택을 완료할 때까지 기다립니다.
-
-
dismissed가 true이거나 사용자가 선택 없이 프롬프트를 닫았으면, p를 "
AbortError"DOMException으로 reject 하고 중단합니다. -
result를 빈 목록으로 둡니다.
-
entries의 각 entry에 대해:
-
entry가 사용자 에이전트에 의해 이 웹사이트에 노출되는 것이 너무 민감하거나 위험하다고 판단되면:
-
선택된 파일 또는 디렉터리가 이 웹사이트에 노출될 수 없다고 사용자에게 알립니다.
-
사용자 에이전트의 재량에 따라, 이 병렬 단계의 시작으로 돌아가거나 p를 "
AbortError"DOMException으로 reject 하고 중단합니다.
-
-
entry와 연관된 새
FileSystemFileHandle을 result에 추가합니다.
-
-
options["
id"], entries[0] 및 environment를 사용하여 선택된 디렉터리를 기억합니다. -
global의 브라우징 컨텍스트에서 활성화 알림 단계를 수행합니다.
참고: 이를 통해 웹사이트는 사용자 활성화를 요구할 수 있는 반환된 핸들에 대한 작업을 즉시 수행할 수 있습니다.
-
p를 result로 resolve 합니다.
-
-
p를 반환합니다.
- handle = await window .
showSaveFilePicker( options ) -
사용자가 단일 파일을 선택할 수 있도록 하는 파일 선택기를 표시하며, 선택된 파일에 대한 핸들을 반환합니다. 선택된 파일이 이미 존재하지 않아도 됩니다. 선택된 파일이 존재하지 않으면 이 메서드가 반환되기 전에 새로운 빈 파일이 생성되며, 그렇지 않으면 기존 파일이 이 메서드가 반환되기 전에 지워집니다.
- handle = await window .
showSaveFilePicker({suggestedName: "README.md" }) -
제안된 "README.md" 파일 이름을 기본 파일 이름으로 미리 채워진 파일 선택기를 표시합니다. 저장할 파일 이름으로.
showSaveFilePicker()에 추가 options를 전달하여 웹사이트가 사용자가 선택할 파일 유형과 파일 선택기가 열릴 디렉터리를 나타낼 수 있습니다. 자세한 내용은 § 3.2 File picker options를 참조하십시오. -
accepts options를 options를 사용하여 수락 유형을 처리한 결과로 둡니다.
-
starting directory를 options["
id"], options["startIn"] 및 environment를 사용하여 선택기가 시작할 디렉터리를 결정한 결과로 둡니다. -
global을 environment의 global object로 둡니다.
-
environment가 파일 선택기를 표시할 수 있는지 확인합니다.
-
p를 새로운 프라미스로 둡니다.
-
다음 단계를 병렬로 실행합니다:
-
선택적으로, 이 알고리즘의 이전 실행이 종료될 때까지 기다립니다.
-
사용자에게 정확히 하나의 파일을 선택하도록 요청하는 프롬프트를 표시합니다. 표시된 프롬프트는 표시된 파일 목록을 필터링하기 위해 accepts options 중 하나를 선택할 수 있도록 해야 합니다. 이것이 어떻게 구현되고 이 프롬프트가 어떻게 보이는지는 implementation-defined입니다. accepts options가 UI에 표시되면 선택된 옵션도 사용자 제공 파일 이름에 추가할 확장자를 제안하는 데 사용되어야 하지만 필수 사항은 아닙니다. 특히 사용자 에이전트는
".lnk"또는".local"로 끝나는 것과 같은 잠재적으로 위험한 접미사를 무시할 수 있습니다.가능하다면 이 프롬프트는 starting directory를 표시하도록 시작해야 합니다.
options["
suggestedName"] 이 존재하고 null이 아니면, 파일 선택기 프롬프트는 options["suggestedName"] 을 기본 이름으로 미리 채워집니다. 저장할 파일 이름으로.suggestedName과 accepts options 간의 상호 작용은 implementation-defined입니다.suggestedName이 너무 위험하다고 판단되면, 사용자 에이전트는 제안된 파일 이름을 무시하거나 정리해야 하며, 다운로드로 가져올 때 수행되는 정리와 유사합니다.참고: 사용자 에이전트는 예를 들어 accepts options에서
suggestedName과 일치하는 옵션을 기본 필터로 선택할 수 있습니다. -
사용자가 선택을 완료할 때까지 기다립니다.
-
사용자가 선택 없이 프롬프트를 닫았으면, p를 "
AbortError"DOMException으로 reject 하고 중단합니다. -
entry를 선택된 파일을 나타내는 파일 항목으로 둡니다.
-
entry가 사용자 에이전트에 의해 이 웹사이트에 노출되는 것이 너무 민감하거나 위험하다고 판단되면:
-
사용자에게 선택된 파일 또는 디렉터리가 이 웹사이트에 노출될 수 없다고 알립니다.
-
사용자 에이전트의 재량에 따라, 이 병렬 단계의 시작으로 돌아가거나 p를 "
AbortError"DOMException으로 reject 하고 중단합니다.
-
-
result를 entry와 연관된 새로운
FileSystemFileHandle로 설정합니다. -
options["
id"], entry 및 environment를 사용하여 선택된 디렉터리를 기억합니다. -
global의 브라우징 컨텍스트에서 활성화 알림 단계를 수행합니다.
참고: 이를 통해 웹사이트는 사용자 활성화를 요구할 수 있는 반환된 핸들에 대한 작업을 즉시 수행할 수 있습니다.
-
p를 result로 resolve 합니다.
-
-
p를 반환합니다.
- handle = await window .
showDirectoryPicker()- handle = await window .
showDirectoryPicker()({mode: 'read' }) - handle = await window .
-
사용자가 단일 디렉터리를 선택할 수 있도록 하는 디렉터리 선택기를 표시하며, 사용자가 읽기 권한을 부여하면 선택된 디렉터리에 대한 핸들을 반환합니다.
- handle = await window .
showDirectoryPicker()({mode: 'readwrite' }) -
사용자가 단일 디렉터리를 선택할 수 있도록 하는 디렉터리 선택기를 표시하며, 선택된 디렉터리에 대한 핸들을 반환합니다. 사용자 에이전트는 이 핸들에 대한 읽기 및 쓰기 권한 요청을 하나의 후속 프롬프트로 결합할 수 있습니다.
-
starting directory를 options["
id"], options["startIn"] 및 environment를 사용하여 선택기가 시작할 디렉터리를 결정한 결과로 둡니다. -
global을 environment의 global object로 둡니다.
-
environment가 파일 선택기를 표시할 수 있는지 확인합니다.
-
p를 새로운 프라미스로 둡니다.
-
다음 단계를 병렬로 실행합니다:
-
선택적으로, 이 알고리즘의 이전 실행이 종료될 때까지 기다립니다.
-
filePickerOptions를 빈 맵으로 둡니다.
-
filePickerOptions["multiple"]을 false로 설정합니다.
-
dismissed를 null과 filePickerOptions로 WebDriver BiDi 파일 대화 상자가 열린 결과로 둡니다.
-
dismissed가 false이면:
-
사용자에게 디렉터리를 선택하도록 요청하는 프롬프트를 표시합니다.
가능하다면 이 프롬프트는 starting directory를 표시하도록 시작해야 합니다.
-
사용자가 선택을 완료할 때까지 기다립니다.
-
-
dismissed가 true이거나 사용자가 선택 없이 프롬프트를 닫았으면, p를 "
AbortError"DOMException으로 reject 하고 중단합니다. -
entry를 선택된 디렉터리를 나타내는 디렉터리 항목으로 둡니다.
-
entry가 사용자 에이전트에 의해 이 웹사이트에 노출되는 것이 너무 민감하거나 위험하다고 판단되면:
-
사용자에게 선택된 파일 또는 디렉터리가 이 웹사이트에 노출될 수 없다고 알립니다.
-
사용자 에이전트의 재량에 따라, 이 병렬 단계의 시작으로 돌아가거나 p를 "
AbortError"DOMException으로 reject 하고 중단합니다.
-
-
result를 entry와 연관된 새로운
FileSystemDirectoryHandle로 설정합니다. -
options["
id"], entry 및 environment를 사용하여 선택된 디렉터리를 기억합니다. -
desc를
FileSystemPermissionDescriptor로 둡니다. -
desc["
name"] 을 "file-system" 으로 설정합니다. -
desc["
handle"] 을 result로 설정합니다. -
status를 desc에 대해 PermissionStatus를 생성한 결과로 둡니다.
-
desc를 사용하기 위해 권한을 요청합니다.
-
desc 및 status에 대해 기본 권한 쿼리 알고리즘을 실행합니다.
-
status가 "
granted" 가 아니면, result를 "AbortError"DOMException으로 reject 하고 중단합니다. -
p를 result로 resolve 합니다.
-
-
p를 반환합니다.
- handle = await item .
getAsFileSystemHandle() -
드래그된 항목이 파일이면
FileSystemFileHandle객체를 반환하고 드래그된 항목이 디렉터리이면FileSystemDirectoryHandle객체를 반환합니다. -
DataTransferItem객체가 읽기/쓰기 모드 또는 읽기 전용 모드에 있지 않으면null로 해결된 프라미스를 반환합니다. -
드래그 데이터 항목 종류가 File이 아니면,
null로 해결된 프라미스를 반환합니다. -
p를 새로운 프라미스로 둡니다.
-
다음 단계를 병렬로 실행합니다:
-
entry를 드래그된 파일 또는 디렉터리를 나타내는 파일 시스템 항목으로 둡니다.
-
entry가 파일 항목이면:
-
handle를 entry와 연관된
FileSystemFileHandle로 둡니다.
-
-
그렇지 않으면 entry가 디렉터리 항목이면:
-
handle를 entry와 연관된
FileSystemDirectoryHandle로 둡니다.
-
-
p를 entry로 resolve 합니다.
-
-
p를 반환합니다.
-
사용자 에이전트 자체를 포함하는 디렉터리 또는 디렉터리.
-
사용자 에이전트가 웹사이트 저장소를 저장하는 디렉터리.
-
시스템 파일이 포함된 디렉터리(예: Windows의
C:\Windows). -
Linux에서 저수준 장치에 대한 액세스를 제공하는
/dev/,/sys, 및/proc과 같은 디렉터리. -
사용자의 전체 "home" 디렉터리. 홈 디렉터리 내부의 개별 파일 및 디렉터리는 여전히 허용되어야 하지만, 사용자 에이전트는 일반적으로 전체 디렉터리에 대한 공백 액세스를 사용자가 부여하도록 허용하지 않아야 합니다.
-
다운로드된 파일이 일반적으로 저장되는 디렉터리(사용자 에이전트에 다운로드용 기본 디렉터리가 있는 경우). 디렉터리 내부의 개별 파일은 여전히 허용되지만, 전체 디렉터리는 사용자가 깨닫는 것보다 더 많은 데이터를 유출할 위험이 있습니다.
-
쓰기 파일을 선택할 때 이름이
.lnk"로 끝나는 파일. Windows에서 이러한 파일에 쓰는 것은 다른 운영 체제에서 심볼릭 링크를 생성하는 것과 유사하며, 사용자가 노출하려는 파일에 액세스하도록 속이려고 시도하는 데 사용할 수 있습니다. -
쓰기 파일을 선택할 때 이름이
.local"로 끝나는 파일. Windows는 이러한 파일을 사용하여 로드할 DLL을 결정하며, 따라서 이러한 파일에 쓰는 것은 코드를 실행하도록 하는 데 사용할 수 있습니다.
StartInDirectory
startIn 및 환경 설정 객체 environment가 주어지면 다음 단계를 실행합니다:
3.3.
showOpenFilePicker()
메서드
showOpenFilePicker(options) 메서드는
호출되었을 때 다음 단계를 실행해야 합니다:
3.4.
showSaveFilePicker()
메서드
suggestedName
옵션은 Chrome 91에서 처음 도입되었습니다.
showSaveFilePicker(options) 메서드는
호출되었을 때 다음 단계를 실행해야 합니다:
3.5.
showDirectoryPicker()
메서드
id
및 startIn
필드는 각각 id
및 startIn
필드와 동일하게 작동합니다.
이러한 필드를 사용하는 방법에 대한 자세한 내용은 § 3.2.2 Starting
Directory를 참조하십시오.
showDirectoryPicker(options)
메서드는 호출되었을 때 다음 단계를 실행해야 합니다:
3.6. 드래그 앤 드롭
partial interface DataTransferItem {Promise <FileSystemHandle ?>getAsFileSystemHandle (); };
드래그 앤 드롭 작업 중에 드래그된 파일 및 디렉터리 항목은 각각 파일 항목 및 디렉터리 항목 과 연관됩니다.
getAsFileSystemHandle()
메서드 단계는 다음과 같습니다:
elem. addEventListener( 'dragover' , ( e) => { // Prevent navigation. e. preventDefault(); }); elem. addEventListener( 'drop' , async ( e) => { e. preventDefault(); const fileHandlesPromises= [... e. dataTransfer. items] . filter( item=> item. kind=== 'file' ) . map( item=> item. getAsFileSystemHandle()); for await ( const handleof fileHandlesPromises) { if ( handle. kind=== 'directory' ) { console. log( `Directory: ${ handle. name} ` ); } else { console. log( `File: ${ handle. name} ` ); } } });
이것은 현재 드롭된 파일 및 디렉터리에 대한 액세스를 제공하는 다른 API와 일관성을 위해 너무 민감하거나 위험한 디렉터리에 대한 액세스를 차단하지 않습니다. 그러나 이는 로컬 파일 시스템 핸들 생성기와 일관되지 않으므로 이를 재고할 수 있습니다.
4. 접근성 고려 사항
이 섹션은 비규범적입니다.
이 규격이 사용자 인터페이스에 정보를 표시할 때, 구현자는 플랫폼의 OS 수준 접근성 지침을 따르기를 원할 것입니다.
5. 개인정보 보호 고려 사항
이 섹션은 비규범적입니다.
이 API는 기존
<input type=file>
및 <input type=file webkitdirectory> API가 이미 하는 것보다 웹사이트에 데이터에 대한 더 많은 읽기 액세스를 제공하지 않습니다.
더욱이 이 API와 유사하게 모든
파일 및 디렉터리에 대한 액세스는 파일 또는 디렉터리 선택기에 의해 명시적으로 게이트됩니다.
그러나 이 새로운 API에는 몇 가지 주요 개인정보 보호 위험이 있습니다:
5.1. 사용자가 의도한 것보다 더 많거나 더 민감한 파일에 대한 액세스를 부여하는 경우.
이것은 이 API의 새로운 위험이 아니지만, 사용자 에이전트는 사용자가 웹사이트에 액세스를 부여하는 것이 무엇인지 정확히 알도록 해야 합니다. 이는 특히 디렉터리에 대한 액세스를 부여할 때 중요하며, 사용자가 그 디렉터리에 실제로 얼마나 많은 파일이 존재하는지 즉시 명확하지 않을 수 있습니다.
관련 위험은 특히 민감한 데이터에 대한 액세스입니다. 이는 사용자 에이전트의 구성 데이터, 네트워크 캐시 또는 쿠키 저장소, 또는 비밀번호 파일과 같은 운영 체제 구성 데이터와 같은 것을 포함할 수 있습니다. 이를 보호하기 위해 사용자 에이전트는 디렉터리 선택기에서 사용자가 선택할 수 있는 디렉터리를 제한하는 것이 권장되며, 잠재적으로 파일 선택기에서 사용자가 선택할 수 있는 파일도 제한합니다. 이렇게 하면 특히 민감한 데이터를 포함하는 디렉터리에 실수로 액세스하는 것을 훨씬 어렵게 만들 수 있습니다. 이 API가 유용하도록 액세스를 제한하면서 민감한 데이터를 포함할 수 있는 디렉터리를 제한하는 올바른 균형을 유지해야 합니다. 결국, 이 API는 사용자가 가장 개인적인 데이터를 웹사이트와 상호 작용할 수 있도록 의도적으로 허용합니다.
사용자 에이전트가 제한해야 할 수 있는 디렉터리의 예는 다음과 같습니다:
5.2. 웹사이트가 이 API를 사용하여 사용자를 추적하려는 경우.
이 API는 브라우징 데이터를 지우는 것을 통해 사용자를 추적하는 데 사용할 수 있습니다. 이는 기존 파일 액세스 API와 달리 사용자 에이전트가 파일이나 디렉터리에 대한 영구 액세스를 부여할 수 있고 재프롬프트할 수 있기 때문입니다. 파일에 쓰기 기능을 결합하면 웹사이트는 사용자의 디스크에 식별자를 영구적으로 저장할 수 있습니다. 브라우징 데이터를 지워도 이러한 파일에는 영향을 미치지 않으므로 이러한 식별자는 이러한 작업을 통해 유지됩니다.
이 위험은 브라우징 데이터를 지우면 웹사이트가 유지한 모든 핸들이 지워진다는 사실로 어느 정도 완화됩니다 (예: IndexedDB에 유지됨), 따라서 브라우징 데이터가 지워진 후 웹사이트는 권한을 재요청할 핸들을 갖지 않습니다. 더욱이 사용자 에이전트는 웹사이트가 액세스할 수 있는 파일 및 디렉터리가 무엇인지 명확히 하고, 특히 신뢰할 수 있는 출처(예: "설치된" 웹 애플리케이션으로 제한된 영구 권한)에 대해 권한 부여를 자동으로 만료하도록 권장됩니다.
사용자 에이전트는 또한 사용자가 부여한 권한을 취소할 수 있는 방법을 제공하는 것이 권장됩니다. 브라우징 데이터를 지우면 모든 권한이 취소되는 것으로 예상됩니다.
5.3. 자사 대 제3자 컨텍스트.
제3자 컨텍스트에서(예: iframe이 최상위 프레임의 출처와 일치하지 않음) 웹사이트는 이미 액세스할 수 있는 데이터를 초과하는 데이터에 액세스할 수 없습니다. 여기에는 로컬
파일 시스템 핸들 생성기를 통해 새 파일 또는 디렉터리에 액세스하는 것과 기존 핸들에 대한 더 많은 권한을 요청하는 requestPermission
API가 포함됩니다.
핸들은 동일 출처 목적지로만 메시지 전송될 수 있습니다. 핸들을 크로스-출처 목적지로 보내려고 시도하면 messageerror
이벤트가 발생합니다.
6. 보안 고려 사항
이 섹션은 비규범적입니다.
이 API는 디스크의 기존 파일을 수정하고 새 파일에 쓰는 웹사이트의 능력을 제공합니다. 이는 몇 가지 중요한 보안 고려 사항이 있습니다:
6.1. 맬웨어
이 API는 웹사이트가 사용자의 시스템에 맬웨어를 저장하거나 실행하려고 시도할 수 있습니다. 이 위험을 완화하기 위해 이 API는 파일을 실행 가능으로 표시할 수 있는 방법을 제공하지 않습니다 (다른 한편으로 이미 실행 가능한 파일은 이 API를 통해 수정된 후에도 여전히 실행 가능할 수 있지만). 더욱이 사용자 에이전트는 이 API에 의해 생성되거나 수정된 파일에 Mark-of-the-Web과 같은 것을 적용하는 것이 권장됩니다.
마지막으로, 사용자 에이전트는 이 API에 의해 수정된 파일의 콘텐츠를 맬웨어 스캔 및 안전 브라우징 검사를 통해 확인하는 것이 권장되며, 이미 강력한 외부 신뢰 관계가 존재하지 않는 한 그렇습니다. 물론 이는 이 API의 성능 특성에 영향을 미칩니다.
6.2. 랜섬웨어 공격
또 다른 위험 요소는 랜섬웨어 공격입니다. 위에서 설명한 민감한 디렉터리에 대한 액세스를 차단하는 제한은 그러한 공격이 할 수 있는 피해를 제한합니다. 또한 사용자 에이전트는 파일에 대한 쓰기 액세스를 적절하다고 판단하는 세분성으로 부여할 수 있습니다.
6.3. 사용자의 디스크 채우기
버킷 파일 시스템의 파일을 제외하고 이 API에 의해 작성된 파일은 저장소 할당량의 적용을 받지 않습니다. 따라서 웹사이트는 할당량에 의해 제한되지 않고 사용자의 디스크를 채울 수 있습니다 (큰 파일을 다운로드하는 것을 트리거하여 클라이언트 측에서 생성된 잠재적으로 큰 파일을 생성하더라도 할당량이 관리되는 저장소에서도 여전히 가능하지만, 저장소 할당량은 일반적으로 사용 가능한 디스크 공간의 양에 따라 달라지지 않습니다).
이 API 없이 웹사이트는 할당량 제한의 적용을 받지 않는 디스크에 데이터를 쓸 수 있습니다.
큰 파일을 다운로드하는 것을 트리거하여 (잠재적으로 클라이언트 측에서 생성된, 네트워크 오버헤드를 유발하지 않음). truncate()
의 존재와 파일 끝을 지나 큰 오프셋으로 쓰는 것은 훨씬 쉽고 낮은 비용으로 큰 파일을 생성합니다. 그러나 대부분의 파일 시스템은 희소 파일을 지원하므로 실제로 그러한 파일이 디스크
공간을 많이 차지하지 않을 수 있습니다 (일반적으로 사용되는 파일 시스템의 대부분은 파일 크기를 조정하거나 파일 끝을 지나 찾는 데 의해 생성된 NUL 바이트를 실제로 저장하지
않습니다).
어떤 완화 조치가 할당량 관리 저장소나 기존 다운로드 메커니즘을 통해 웹사이트가 디스크를 채우는 것을 방지하기 위해 사용자 에이전트가 사용하는지, 웹사이트가 이 API를 사용하여 디스크에 쓸 때도 동일하게 적용해야 합니다.