Interfejs File System Access API umożliwia aplikacjom internetowym odczytywanie i zapisywanie zmian bezpośrednio w plikach i folderach na urządzeniu użytkownika.
Czym jest interfejs File System Access API?
Interfejs File System Access API umożliwia programistom tworzenie zaawansowanych aplikacji internetowych, które współpracują z pliki na lokalnym urządzeniu użytkownika, takie jak IDE, edytory zdjęć i filmów czy edytory tekstu. Po użytkownik udziela aplikacji internetowej dostępu, ten interfejs API umożliwia odczyt lub zapisywanie zmian bezpośrednio w plikach foldery na urządzeniu użytkownika. Oprócz odczytu i zapisu plików interfejs File System Access API zapewnia otwieranie katalogu i wyliczenie jego zawartości.
Jeśli masz już doświadczenie w czytaniu i pisaniu plików, pokażę Ci, znanych Ci filmów. Mimo to zachęcam do jej przeczytania, ponieważ nie wszystkie systemy są takie same.
Interfejs File System Access API jest obsługiwany przez większość przeglądarek Chromium Windows, macOS, ChromeOS i Linux. Istotnym wyjątkiem jest Brave, obecnie dostępne tylko za flagą. Pracujemy nad obsługą Androida w kontekście strony crbug.com/1011535.
Używanie interfejsu File System Access API
Aby przedstawić możliwości i przydatność interfejsu File System Access API, napisałem jeden tekst w jednym pliku . Za jego pomocą można otworzyć plik tekstowy, edytować go, zapisać zmiany z powrotem na dysku oraz rozpocząć utwórz nowy plik i zapisz zmiany na dysku. To nic niezwykłego, ale zawiera wystarczająco dużo, aby pomóc Ci rozumieją pojęcia.
Obsługa przeglądarek
Wykrywanie cech
Aby dowiedzieć się, czy interfejs File System Access API jest obsługiwany, sprawdź, czy metoda selektora który Cię interesuje.
if ('showOpenFilePicker' in self) {
// The `showOpenFilePicker()` method of the File System Access API is supported.
}
Wypróbuj
Zobacz, jak działa interfejs File System Access API w edytora tekstu.
Odczytywanie pliku z lokalnego systemu plików
W pierwszym przykładzie chcę przedstawić użytkownikom prośbę o wybranie pliku, a następnie go otworzyć i przeczytać. z dysku.
Poproś użytkownika o wskazanie pliku do przeczytania
Punkt wejścia interfejsu File System Access API to
window.showOpenFilePicker()
Po wywołaniu
wyświetla się okno wyboru plików,
i prosi o wybranie pliku. Po wybraniu pliku interfejs API zwraca tablicę pliku.
uchwytów. Opcjonalny parametr options
pozwala wpływać na działanie selektora plików, np.
Na przykład pozwalając użytkownikowi wybrać wiele plików, katalogów lub różnych typów plików.
Jeśli nie określisz żadnych opcji, selektor plików umożliwi użytkownikowi wybranie pojedynczego pliku. To jest
doskonale sprawdza się w edytorze tekstu.
Podobnie jak wiele innych zaawansowanych interfejsów API, showOpenFilePicker()
trzeba wywoływać w bezpiecznym miejscu
kontekst i musi być wywoływana gestem użytkownika.
let fileHandle;
butOpenFile.addEventListener('click', async () => {
// Destructure the one-element array.
[fileHandle] = await window.showOpenFilePicker();
// Do something with the file handle.
});
Gdy użytkownik wybierze plik, showOpenFilePicker()
zwraca tablicę nicków, w tym przypadku
jednoelementowej tablicy z jednym FileSystemFileHandle
, który zawiera właściwości oraz
i metod interakcji z plikiem.
Warto zachować odwołanie do uchwytu pliku, aby móc go użyć później. Będzie potrzebne do zapisania zmian w pliku lub wykonania innych operacji na pliku.
Odczytywanie pliku z systemu plików
Teraz, gdy masz już nick dla pliku, możesz pobrać jego właściwości lub uzyskać dostęp do samego pliku.
Na razie przeczytam tylko jego treść. Połączenie z numerem handle.getFile()
zwraca File
który zawiera obiekt blob. Aby pobrać dane z obiektu blob, wywołaj jeden z jego
, (slice()
,
stream()
,
text()
lub
arrayBuffer()
).
const file = await fileHandle.getFile();
const contents = await file.text();
Obiekt File
zwrócony przez funkcję FileSystemFileHandle.getFile()
jest czytelny tylko tak długo, jak długo
bazowy plik na dysku nie uległ zmianie. Jeśli plik na dysku zostanie zmodyfikowany, obiekt File
stanie się
nie można odczytać i trzeba wywołać ponownie getFile()
, aby uzyskać nowy obiekt File
w celu odczytania zmienionych
i skalowalnych danych.
Podsumowanie
Gdy użytkownik kliknie przycisk Otwórz, w przeglądarce pojawi się selektor plików. Gdy wybierzą plik,
aplikacja odczytuje treści i umieszcza je w elemencie <textarea>
.
let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});
Zapisz plik w lokalnym systemie plików
W edytorze tekstu możesz zapisać plik na dwa sposoby: Zapisz lub Zapisz jako. Zapisz zapisuje zmiany z powrotem w oryginalnym pliku przy użyciu pobranego wcześniej uchwytu pliku. Ale zaoszczędź As tworzy nowy plik i dlatego wymaga nowego uchwytu.
Utwórz nowy plik
Aby zapisać plik, wywołaj showSaveFilePicker()
. Wyświetli się selektor plików.
w „zapisz” w którym użytkownik może wybrać nowy plik, którego chce użyć do zapisania. Dla tekstu
Chciałem też, by automatycznie dodawało rozszerzenie .txt
, więc dodałem
.
async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}
Zapisz zmiany na dysku
Cały kod do zapisywania zmian w pliku znajdziesz w mojej prezentacji edytora tekstu na stronie
GitHub Podstawowe interakcje systemu plików są
fs-helpers.js
Najprościej wygląda to tak, jak pokazano poniżej.
Omówię każdy krok i wyjaśnię go.
// fileHandle is an instance of FileSystemFileHandle..
async function writeFile(fileHandle, contents) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();
}
Do zapisywania danych na dysku wykorzystywany jest obiekt FileSystemWritableFileStream
, podklasa
z WritableStream
. Utwórz strumień, wywołując w pliku funkcję createWritable()
i „obsługiwany obiekt”. Po wywołaniu funkcji createWritable()
przeglądarka najpierw sprawdza, czy użytkownik udzielił zgody
uprawnienia do zapisu w pliku. Jeśli uprawnienia do zapisu nie zostały przyznane, przeglądarka wyświetli komunikat
użytkownik musi uzyskać odpowiednie uprawnienia. Jeśli uprawnienia nie są przyznane, createWritable()
wysyła zapytanie
DOMException
, a aplikacja nie będzie mogła zapisać w tym pliku. W edytorze tekstu
Obiekty DOMException
są obsługiwane w metodzie saveFile()
.
Metoda write()
pobiera ciąg znaków, który jest niezbędny w edytorze tekstu. Może to też zająć
BufferSource lub Blob. Możesz na przykład użyć potoku, aby przesłać strumień bezpośrednio do
:
async function writeURLToFile(fileHandle, url) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Make an HTTP request for the contents.
const response = await fetch(url);
// Stream the response into the file.
await response.body.pipeTo(writable);
// pipeTo() closes the destination pipe by default, no need to close it.
}
Możesz też seek()
lub truncate()
w strumieniu, aby zaktualizować
w określonym miejscu lub zmień jego rozmiar.
Określanie sugerowanej nazwy pliku i katalogu początkowego
W wielu przypadkach może być konieczne, aby aplikacja sugerowała domyślną nazwę pliku lub domyślną lokalizację. Na przykład tekst
Edytor może zaproponować domyślną nazwę pliku Untitled Text.txt
zamiast Untitled
. Ty
można to osiągnąć, przekazując właściwość suggestedName
w opcjach showSaveFilePicker
.
const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});
To samo dotyczy domyślnego katalogu początkowego. Jeśli tworzysz edytor tekstu,
otwierać okno zapisywania lub otwierania pliku w domyślnym folderze documents
, natomiast w przypadku obrazu
w edytorze pictures
. Możesz zaproponować domyślny początek
przez przekazanie właściwości startIn
do funkcji showSaveFilePicker
, showDirectoryPicker()
lub
showOpenFilePicker
podobnych metod.
const fileHandle = await self.showOpenFilePicker({
startIn: 'pictures'
});
Oto lista dobrze znanych katalogów systemowych:
desktop
: katalog na komputerze użytkownika, jeśli istnieje taki element.documents
: katalog, w którym zwykle przechowywane są dokumenty utworzone przez użytkownika.downloads
: katalog, w którym zwykle są przechowywane pobrane pliki.music
: katalog, w którym zwykle są przechowywane pliki audio.pictures
: katalog, w którym zwykle są przechowywane zdjęcia i inne obrazy.videos
: katalog, w którym zwykle są przechowywane materiały wideo.
Poza dobrze znanymi katalogami systemowymi można również przekazać istniejący uchwyt pliku lub katalogu jako
wartość w kolumnie startIn
. Okno zostanie otwarte w tym samym katalogu.
// Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});
Określanie przeznaczenia różnych selektorów plików
Czasami aplikacje mają różne selektory do różnych celów. Na przykład tekst sformatowany
umożliwia otwieranie plików tekstowych i importowanie obrazów. Domyślnie każdy plik
spowoduje otwarcie go w ostatniej zapamiętanej lokalizacji. Możesz to obejść, przechowując wartości id
dla każdego typu selektora. Jeśli jest określony atrybut id
, implementacja selektora plików zapamiętuje
oddzielnym ostatnim używanym katalogu dla tego zasobu (id
).
const fileHandle1 = await self.showSaveFilePicker({
id: 'openText',
});
const fileHandle2 = await self.showSaveFilePicker({
id: 'importImage',
});
Przechowywanie uchwytów plików lub uchwytów katalogów w IndexedDB
Uchwyty plików i uchwyty katalogów są serializowalne, co oznacza, że możesz zapisać plik lub
uchwyt katalogu do IndexedDB lub wywołanie postMessage()
, aby przesłać je między tym samym najwyższym poziomem
pochodzeniu danych.
Zapisywanie uchwytów plików lub katalogu w IndexedDB oznacza, że możesz zapisywać stan plików lub katalogów, nad którymi pracował użytkownik. Dzięki temu możesz zachować listę lub edytowanych plików, zaproponować ponowne otwarcie ostatniego pliku po otwarciu aplikacji, przywrócenie poprzedniego pliku katalogu usług i nie tylko. W edytorze tekstu przechowuję listę 5 ostatnich plików użytkownika co pozwoliło uzyskać do nich dostęp.
Poniższy przykładowy kod pokazuje przechowywanie i pobieranie uchwytu pliku oraz uchwytu katalogu. Dostępne opcje zobacz, jak to działa w Glitch. (Używam dla zachowania zwięzłości biblioteki idb-keyval).
import { get, set } from 'https://unpkg.com/idb-keyval@5.0.2/dist/esm/index.js';
const pre1 = document.querySelector('pre.file');
const pre2 = document.querySelector('pre.directory');
const button1 = document.querySelector('button.file');
const button2 = document.querySelector('button.directory');
// File handle
button1.addEventListener('click', async () => {
try {
const fileHandleOrUndefined = await get('file');
if (fileHandleOrUndefined) {
pre1.textContent = `Retrieved file handle "${fileHandleOrUndefined.name}" from IndexedDB.`;
return;
}
const [fileHandle] = await window.showOpenFilePicker();
await set('file', fileHandle);
pre1.textContent = `Stored file handle for "${fileHandle.name}" in IndexedDB.`;
} catch (error) {
alert(error.name, error.message);
}
});
// Directory handle
button2.addEventListener('click', async () => {
try {
const directoryHandleOrUndefined = await get('directory');
if (directoryHandleOrUndefined) {
pre2.textContent = `Retrieved directroy handle "${directoryHandleOrUndefined.name}" from IndexedDB.`;
return;
}
const directoryHandle = await window.showDirectoryPicker();
await set('directory', directoryHandle);
pre2.textContent = `Stored directory handle for "${directoryHandle.name}" in IndexedDB.`;
} catch (error) {
alert(error.name, error.message);
}
});
Uchwyty i uprawnienia przechowywanego pliku lub katalogu
Uprawnienia nie zawsze są zachowywane między sesjami, więc sprawdź, czy użytkownik
przyznał(a) uprawnienia do pliku lub katalogu za pomocą: queryPermission()
. Jeśli nie, zadzwoń
requestPermission()
, aby (ponownie) poprosić o nie. To samo działa w przypadku uchwytów plików i katalogów. Ty
muszą uruchomić fileOrDirectoryHandle.requestPermission(descriptor)
lub
fileOrDirectoryHandle.queryPermission(descriptor)
.
W edytorze tekstu utworzyłem metodę verifyPermission()
, która sprawdza, czy użytkownik
użytkownik wyraził zgodę i w razie potrzeby przesyła żądanie.
async function verifyPermission(fileHandle, readWrite) {
const options = {};
if (readWrite) {
options.mode = 'readwrite';
}
// Check if permission was already granted. If so, return true.
if ((await fileHandle.queryPermission(options)) === 'granted') {
return true;
}
// Request permission. If the user grants permission, return true.
if ((await fileHandle.requestPermission(options)) === 'granted') {
return true;
}
// The user didn't grant permission, so return false.
return false;
}
Poprzez przesłanie prośby o uprawnienia do zapisu udało mi się zmniejszyć liczbę próśb o uprawnienia. użytkownik widzi jeden prompt przy otwarciu pliku i przyznaje uprawnienia zarówno do odczytu, jak i do zapisu.
Otwieranie katalogu i wyliczanie jego zawartości
Aby wyliczyć wszystkie pliki w katalogu, wywołaj showDirectoryPicker()
. Użytkownik
wybiera katalog w selektorze, po którym następuje znak FileSystemDirectoryHandle
, co umożliwia wyliczanie plików katalogu i uzyskiwanie do nich dostępu. Domyślnie odczytywane są
dostęp do plików w katalogu, ale jeśli potrzebujesz uprawnień do zapisu, możesz
{ mode: 'readwrite' }
do metody.
butDir.addEventListener('click', async () => {
const dirHandle = await window.showDirectoryPicker();
for await (const entry of dirHandle.values()) {
console.log(entry.kind, entry.name);
}
});
Jeśli musisz dodatkowo uzyskać dostęp do każdego pliku przy użyciu usługi getFile()
, na przykład po to, aby uzyskać indywidualną
rozmiarów plików, nie używaj opcji await
w każdym wyniku po kolei, zamiast tego przetwarzać wszystkie pliki
równoległe, na przykład za pomocą funkcji Promise.all()
.
butDir.addEventListener('click', async () => {
const dirHandle = await window.showDirectoryPicker();
const promises = [];
for await (const entry of dirHandle.values()) {
if (entry.kind !== 'file') {
continue;
}
promises.push(entry.getFile().then((file) => `${file.name} (${file.size})`));
}
console.log(await Promise.all(promises));
});
tworzenie plików i folderów w katalogu oraz uzyskiwanie do nich dostępu;
W katalogu możesz tworzyć pliki i foldery albo uzyskiwać do nich dostęp za pomocą
getFileHandle()
lub odpowiednio getDirectoryHandle()
. Przekazując opcjonalny obiekt options
z kluczem create
i wartością logiczną
true
lub false
, możesz określić, czy należy utworzyć nowy plik lub folder, jeśli nie istnieje.
// In an existing directory, create a new directory named "My Documents".
const newDirectoryHandle = await existingDirectoryHandle.getDirectoryHandle('My Documents', {
create: true,
});
// In this new directory, create a file named "My Notes.txt".
const newFileHandle = await newDirectoryHandle.getFileHandle('My Notes.txt', { create: true });
Rozpoznawanie ścieżki elementu w katalogu
Podczas pracy z plikami lub folderami w katalogu może być pomocne rozwiązanie ścieżki do elementu
w związku z naruszeniem naszych przepisów. Użyj w tym celu metody o błędnej nazwie resolve()
. Aby rozwiązać ten problem,
Element może być bezpośrednim lub pośrednim podrzędnym katalogiem.
// Resolve the path of the previously created file called "My Notes.txt".
const path = await newDirectoryHandle.resolve(newFileHandle);
// `path` is now ["My Documents", "My Notes.txt"]
Usuwanie plików i folderów z katalogu
Jeśli masz dostęp do katalogu, możesz usunąć zawarte w nim pliki i foldery za pomocą
removeEntry()
. W przypadku folderów usuwanie może być opcjonalnie rekurencyjne i obejmować
wszystkich podfolderów i znajdujących się w nich plików.
// Delete a file.
await directoryHandle.removeEntry('Abandoned Projects.txt');
// Recursively delete a folder.
await directoryHandle.removeEntry('Old Stuff', { recursive: true });
Bezpośrednie usuwanie pliku lub folderu
Jeśli masz dostęp do pliku lub uchwytu katalogu, wywołaj remove()
w FileSystemFileHandle
lub
FileSystemDirectoryHandle
, aby go usunąć.
// Delete a file.
await fileHandle.remove();
// Delete a directory.
await directoryHandle.remove();
Zmienianie nazw i przenoszenie plików oraz folderów
Pliki i foldery można przenieść do nowej lokalizacji lub zmienić ich nazwę, wywołując funkcję move()
na
interfejsu FileSystemHandle
. FileSystemHandle
ma interfejsy podrzędne FileSystemFileHandle
i
FileSystemDirectoryHandle
Metoda move()
przyjmuje 1 lub 2 parametry. Pierwszy z nich może
być ciągiem z nową nazwą lub ciągiem FileSystemDirectoryHandle
do folderu docelowego. W
W drugim przypadku opcjonalny drugi parametr jest ciągiem z nową nazwą, więc jego przeniesienie i zmiana nazwy
wystarczy wykonać jeden krok.
// Rename the file.
await file.move('new_name');
// Move the file to a new directory.
await file.move(directory);
// Move the file to a new directory and rename it.
await file.move(directory, 'newer_name');
Integracja metodą „przeciągnij i upuść”
Interfejs HTML metodą „przeciągnij i upuść”
włącz akceptowanie aplikacji internetowych
przeciągnięte i upuszczone pliki
na stronie internetowej. Podczas przeciągania i upuszczania przeciągane elementy pliku i katalogu są powiązane
z wpisami odpowiednio plików i katalogu. DataTransferItem.getAsFileSystemHandle()
zwraca obietnicę z obiektem FileSystemFileHandle
, jeśli przeciągnięty element jest plikiem, a
z obiektem FileSystemDirectoryHandle
, jeśli przeciągnięty element jest katalogiem. Następująca strona
pokazuje to w praktyce. Pamiętaj, że funkcja „Przeciągnij i upuść”
DataTransferItem.kind
to
"file"
w przypadku plików i katalogów, natomiast FileSystemHandle.kind
interfejsu File System Access API jest
"file"
na pliki i "directory"
na katalogi.
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 handle of fileHandlesPromises) {
if (handle.kind === 'directory') {
console.log(`Directory: ${handle.name}`);
} else {
console.log(`File: ${handle.name}`);
}
}
});
Uzyskiwanie dostępu do prywatnego systemu plików punktu początkowego
Prywatny system plików punktu początkowego to punkt końcowy pamięci masowej, który, jak sama nazwa wskazuje, jest prywatny
pochodzenie strony. Przeglądarki zazwyczaj implementują to, zachowując zawartość
pierwotny system plików na dysk, nie jest to przeznaczone dla użytkownika
i łatwo dostępnych rozwiązań. Nie należy również oczekiwać, że pliki lub katalogi o nazwach pasujących do zapytania
nazwy elementów podrzędnych początkowego systemu plików istnieją. Chociaż przeglądarka może sprawiać takie wrażenie,
są pliki, które są używane wewnętrznie – jest to prywatny system plików punktu początkowego – przeglądarka może zapisywać
te „pliki” w bazie danych
lub innej strukturze danych. Zasadniczo, jeśli używasz tego interfejsu API,
nie spodziewaj się, że utworzone pliki będą w innym miejscu na dysku twardym i identyczne. W tych dniach:
do prywatnego systemu plików punktu początkowego, gdy będziesz mieć dostęp do katalogu głównego FileSystemDirectoryHandle
.
const root = await navigator.storage.getDirectory();
// Create a new file handle.
const fileHandle = await root.getFileHandle('Untitled.txt', { create: true });
// Create a new directory handle.
const dirHandle = await root.getDirectoryHandle('New Folder', { create: true });
// Recursively remove a directory.
await root.removeEntry('Old Stuff', { recursive: true });
Uzyskiwanie dostępu do plików zoptymalizowanych pod kątem wydajności z prywatnego systemu plików punktu początkowego
Prywatny system plików punktu początkowego zapewnia opcjonalny dostęp do specjalnego rodzaju pliku, który zapewnia
optymalizację pod kątem wydajności, na przykład przez oferowanie lokalnego i wyłącznego dostępu do
treści. W Chromium 102 i nowszych wersjach dostępna jest dodatkowa metoda w prywatnym systemie plików źródła, dla której
upraszczanie dostępu do plików: createSyncAccessHandle()
(na potrzeby synchroniczne operacje odczytu i zapisu).
Ekspozycja zostanie udostępniona FileSystemFileHandle
, ale wyłącznie w
Skrypty internetowe.
// (Read and write operations are synchronous,
// but obtaining the handle is asynchronous.)
// Synchronous access exclusively in Worker contexts.
const accessHandle = await fileHandle.createSyncAccessHandle();
const writtenBytes = accessHandle.write(buffer);
const readBytes = accessHandle.read(buffer, { at: 1 });
Polyfill
Nie można w pełni wypełnić metod interfejsu File System Access API.
- Metodę
showOpenFilePicker()
można określić w przybliżeniu za pomocą elementu<input type="file">
. - Metodę
showSaveFilePicker()
można symulować za pomocą elementu<a download="file_name">
, ale uruchamia to pobieranie programowe i nie pozwala na zastępowanie istniejących plików. - Metoda
showDirectoryPicker()
może być nieco emulowana za pomocą metody niestandardowej<input type="file" webkitdirectory>
.
Opracowaliśmy bibliotekę o nazwie browser-fs-access, która wykorzystuje Interfejs System Access API wszędzie tam, gdzie jest to możliwe i który nawiązuje do tych najlepszych najlepszych opcji przypadków.
Bezpieczeństwo i uprawnienia
Zespół Chrome zaprojektował i wdrożył interfejs File System Access API, kierując się podstawowymi zasadami w artykule Kontrola nad dostępem do zaawansowanych funkcji platform internetowych, w tym kontrolę i przejrzystość oraz ergonomię użytkownika.
Otwieranie pliku lub zapisywanie nowego
![Okno wyboru plików umożliwiające otwarcie pliku do odczytu](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/file-system-access/image/file-picker-open-file-8cb5f6783ee89.jpg?authuser=8&hl=pl)
Po otwarciu pliku użytkownik przyznaje uprawnienia do odczytu pliku lub katalogu za pomocą selektora plików.
Otwarty selektor plików można wyświetlić gestem użytkownika tylko wtedy, gdy jest on wyświetlany z bezpiecznej
kontekstu. Jeśli użytkownik zmieni zdanie, może anulować zaznaczenie w pliku.
, a witryna nie uzyska dostępu do żadnych elementów. Działa to tak samo jak w przypadku
<input type="file">
element.
![Selektor plików umożliwiający zapisanie pliku na dysku.](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/file-system-access/image/file-picker-save-file-bd54ae001799a.jpg?authuser=8&hl=pl)
Podobnie, gdy aplikacja internetowa chce zapisać nowy plik, przeglądarka wyświetla selektor plików, co umożliwia użytkownikowi określenie nazwy i lokalizacji nowego pliku. Zapisują nowy plik (w przeciwieństwie do zastępowania istniejącego pliku) selektor plików przyznaje aplikacji uprawnienia i zapisać dane w pliku.
Foldery z ograniczonym dostępem
Aby chronić użytkowników i ich dane, przeglądarka może ograniczyć użytkownikowi możliwość zapisywania w niektórych na przykład podstawowe foldery systemu operacyjnego, takie jak Windows, czy foldery biblioteki macOS. W takim przypadku przeglądarka wyświetla pytanie i prosi użytkownika o wybranie innej wartości. folderu Dysku.
Modyfikowanie istniejącego pliku lub katalogu
Aplikacja internetowa nie może modyfikować pliku na dysku bez uzyskania wyraźnej zgody użytkownika.
Prośba o zgodę
Jeśli ktoś chce zapisać zmiany w pliku, któremu wcześniej przyznała uprawnienia do odczytu, przeglądarka wyświetla monit o przyznanie uprawnień z prośbą o zgodę na zapisywanie zmian na dysku. Prośba o uprawnienia może być aktywowana tylko gestem użytkownika, na przykład przez kliknięcie przycisku Zapisz Przycisk
![Prośba o zgodę jest wyświetlana przed zapisaniem pliku.](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/file-system-access/image/permission-prompt-shown-p-823d180f97ad5.png?authuser=8&hl=pl)
Aplikacja internetowa, która edytuje wiele plików, np. IDE, może też poprosić o uprawnienia do zapisu. zmienia się w chwili otwarcia.
Jeśli użytkownik wybierze Anuluj i nie przyzna uprawnień do zapisu, aplikacja internetowa nie będzie mogła zapisać zmian w pliku lokalnym. Powinien on zapewniać użytkownikowi alternatywną metodę zapisywania danych, na przykład: na przykład przez udostępnienie sposobu „pobierania” plik lub zapisanie danych w chmurze.
Przejrzystość
![Ikona omniboksu](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/file-system-access/image/omnibox-icon-5797e9a831603.jpg?authuser=8&hl=pl)
Gdy użytkownik zezwoli aplikacji internetowej na zapisywanie pliku lokalnego, w przeglądarce pojawi się ikona na pasku adresu. Kliknięcie ikony otwiera wyskakujące okienko z listą plików przekazanych przez użytkownika . Użytkownik może w każdej chwili cofnąć dostęp.
Trwałość uprawnień
Aplikacja internetowa może dalej zapisywać zmiany w pliku bez pytania, dopóki wszystkie karty punkty początkowe są zamknięte. Po zamknięciu karty witryna utraci do niej pełny dostęp. Gdy następnym razem użytkownik użyje aplikacji internetowej, zostanie ponownie wyświetlona prośba o dostęp do plików.
Prześlij opinię
Chętnie poznamy Twoją opinię na temat interfejsu File System Access API.
Opowiedz nam o konstrukcji interfejsu API
Czy jest coś, co nie działa w interfejsie API zgodnie z oczekiwaniami? Czy może brakuje tu metod lub właściwości potrzebne do realizacji pomysłu? Masz pytanie lub komentarz na temat zabezpieczeń model?
- Zgłoś problem ze specyfikacją w repozytorium GitHub dostępu do systemu plików WICG lub dodaj opinię. do istniejącego problemu.
Problem z implementacją?
Czy wystąpił błąd z implementacją Chrome? Czy implementacja różni się od specyfikacji?
- Zgłoś błąd na https://new.crbug.com. Podaj jak najwięcej szczegółów.
instrukcji odtwarzania i ustaw opcję Komponenty na
Blink>Storage>FileSystem
. Błąd świetnie nadaje się do udostępniania szybkich poprawek.
Planujesz korzystać z interfejsu API?
Planujesz użyć w swojej witrynie interfejsu File System Access API? Twoje publiczne wsparcie pomaga nam potraktować priorytetowo i pokazuje innym dostawcom przeglądarek, jak ważne jest ich zapewnienie.
- Poinformuj nas, jak zamierzasz korzystać z tego narzędzia w wątku poświęconym dysku WICG.
- Wyślij tweeta na adres @ChromiumDev, używając hashtagu
#FileSystemAccess
i daj nam znać, gdzie i jak go używasz.
Przydatne linki
- Publiczne wyjaśnienie
- Specyfikacja dostępu do systemu plików Specyfikacja pliku
- Śledzenie błędu
- Wpis na temat ChromeStatus.com
- Definicje TypeScript
- File System Access API – model zabezpieczeń Chromium
- Komponent Blink:
Blink>Storage>FileSystem
Podziękowania
Specyfikacja interfejsu File System Access API została napisana przez Marijn Kruisselbrink