Izpētiet jaudīgo File System Access API, kas ļauj tīmekļa lietotnēm droši lasīt, rakstīt un pārvaldīt vietējos failus. Visaptverošs ceļvedis globāliem izstrādātājiem.
Vietējās failu sistēmas atvēršana: dziļš ieskats Frontend File System Access API
Gadu desmitiem pārlūkprogramma ir bijusi izolēta vide (sandboxed environment) – droša, bet fundamentāli ierobežota telpa. Viena no tās stingrākajām robežām ir bijusi vietējā failu sistēma. Tīmekļa lietojumprogrammas varēja lūgt jums augšupielādēt failu vai piedāvāt to lejupielādēt, bet ideja par tīmekļa teksta redaktoru, kas atver failu, ļauj to rediģēt un saglabā atpakaļ tajā pašā vietā, bija tīra zinātniskā fantastika. Šis ierobežojums ir bijis galvenais iemesls, kāpēc vietējās darbvirsmas lietojumprogrammas ir saglabājušas savu pārsvaru uzdevumos, kas prasa intensīvu failu manipulāciju, piemēram, video rediģēšanā, programmatūras izstrādē un grafiskajā dizainā.
Šī paradigma tagad mainās. File System Access API, agrāk pazīstama kā Native File System API, sagrauj šo ilggadējo barjeru. Tā nodrošina tīmekļa izstrādātājiem standartizētu, drošu un jaudīgu mehānismu, lai lasītu, rakstītu un pārvaldītu failus un direktorijus lietotāja lokālajā datorā. Tā nav drošības ievainojamība; tā ir rūpīgi izstrādāta evolūcija, kas lietotājam nodod pilnīgu kontroli, izmantojot skaidri izteiktas atļaujas.
Šis API ir stūrakmens nākamās paaudzes progresīvajām tīmekļa lietotnēm (PWA), sniedzot tām iespējas, kas kādreiz bija ekskluzīvas vietējai programmatūrai. Iedomājieties tīmekļa IDE, kas var pārvaldīt lokālu projekta mapi, fotoattēlu redaktoru, kas strādā tieši ar jūsu augstas izšķirtspējas attēliem bez augšupielādes, vai piezīmju lietotni, kas saglabā markdown failus tieši jūsu dokumentu mapē. Tāda ir nākotne, ko nodrošina File System Access API.
Šajā visaptverošajā ceļvedī mēs izpētīsim katru šī transformējošā API aspektu. Mēs iedziļināsimies tā vēsturē, izpratīsim tā galvenos drošības principus, soli pa solim apskatīsim praktiskus koda piemērus lasīšanai, rakstīšanai un direktoriju pārvaldībai, kā arī apspriedīsim progresīvas tehnikas un reālās pasaules lietošanas gadījumus, kas iedvesmos jūsu nākamo projektu.
Failu apstrādes evolūcija tīmeklī
Lai patiesi novērtētu File System Access API nozīmi, ir noderīgi atskatīties uz to, kā pārlūkprogrammas ir apstrādājušas vietējos failus vēsturiski. Šis ceļojums ir bijis pakāpeniska, uz drošību orientēta iterācija.
Klasiskā pieeja: ievades lauki un enkuri
Sākotnējās metodes failu mijiedarbībai bija vienkāršas un stingri kontrolētas:
- Failu lasīšana:
<input type="file">elements gadiem ilgi ir bijis galvenais rīks failu augšupielādei. Kad lietotājs izvēlas failu (vai vairākus failus armultipleatribūtu), lietojumprogramma saņemFileListobjektu. Izstrādātāji pēc tam var izmantotFileReaderAPI, lai nolasītu šo failu saturu atmiņā kā virkni, ArrayBuffer vai datu URL. Tomēr lietojumprogramma nekad neuzzina faila sākotnējo ceļu un tai nav iespēju tajā rakstīt atpakaļ. Katra 'saglabāšanas' operācija faktiski ir 'lejupielāde'. - Failu saglabāšana: Saglabāšana bija vēl netiešāka. Izplatītākā tehnika ietver
<a>(enkura) taga izveidi, tāhrefatribūta iestatīšanu uz datu URI vai Blob URL,downloadatribūta pievienošanu ar ieteikto faila nosaukumu un programmatisku klikšķi uz tā. Šī darbība lietotājam parāda 'Saglabāt kā...' dialoglodziņu, kas parasti pēc noklusējuma atveras 'Lejupielāžu' mapē. Lietotājam ir manuāli jānavigē uz pareizo vietu, ja viņš vēlas pārrakstīt esošu failu.
Veco metožu ierobežojumi
Lai gan funkcionāls, šis klasiskais modelis radīja būtiskus ierobežojumus sarežģītu lietojumprogrammu izveidē:
- Bezstāvokļa mijiedarbība: Savienojums ar failu tiek zaudēts uzreiz pēc tā nolasīšanas. Ja lietotājs rediģē dokumentu un vēlas to saglabāt, lietojumprogramma nevar vienkārši pārrakstīt oriģinālu. Lietotājam ir jālejupielādē jauna kopija, bieži ar modificētu nosaukumu (piemēram, 'dokuments(1).txt'), kas noved pie failu nekārtības un mulsinošas lietotāja pieredzes.
- Nav piekļuves direktorijiem: Nebija mapes jēdziena. Lietojumprogramma nevarēja lūgt lietotājam atvērt visu projekta direktoriju, lai strādātu ar tā saturu, kas ir fundamentāla prasība jebkurai tīmekļa IDE vai koda redaktoram.
- Lietotāja apgrūtinājums: Pastāvīgais cikls 'Atvērt...' -> 'Rediģēt' -> 'Saglabāt kā...' -> 'Navigēt...' -> 'Pārrakstīt?' ir apgrūtinošs un neefektīvs, salīdzinot ar vienkāršo 'Ctrl + S' vai 'Cmd + S' pieredzi vietējās lietojumprogrammās.
Šie ierobežojumi pazemināja tīmekļa lietotnes līdz pārejošu failu patērētāju un radītāju lomai, nevis lietotāja vietējo datu pastāvīgiem redaktoriem. File System Access API tika izstrādāts, lai tieši risinātu šīs nepilnības.
Iepazīstinām ar File System Access API
File System Access API ir mūsdienīgs tīmekļa standarts, kas nodrošina tiešu, kaut arī ar atļaujām aizsargātu, tiltu uz lietotāja vietējo failu sistēmu. Tas ļauj izstrādātājiem veidot bagātīgas, darbvirsmas klases pieredzes, kurās faili un direktoriji tiek uzskatīti par pirmās klases pilsoņiem.
Pamatjēdzieni un terminoloģija
API izpratne sākas ar tā galvenajiem objektiem, kas darbojas kā rokturi vai atsauces uz failu sistēmas elementiem.
FileSystemHandle: Šī ir bāzes saskarne gan failiem, gan direktorijiem. Tā pārstāv vienu ierakstu failu sistēmā un tai ir tādas īpašības kānameunkind('file' vai 'directory').FileSystemFileHandle: Šī saskarne pārstāv failu. Tā manto noFileSystemHandleun nodrošina metodes mijiedarbībai ar faila saturu, piemēram,getFile(), lai iegūtu standartaFileobjektu (metadatu vai satura lasīšanai), uncreateWritable(), lai iegūtu straumi datu rakstīšanai.FileSystemDirectoryHandle: Šī saskarne pārstāv direktoriju. Tā ļauj uzskaitīt direktorija saturu vai iegūt rokturus uz konkrētiem failiem vai apakšdirektorijiem tajā, izmantojot tādas metodes kāgetFileHandle()ungetDirectoryHandle(). Tā nodrošina arī asinhronus iteratorus, lai ciklētu caur tās ierakstiem.FileSystemWritableFileStream: Šī ir jaudīga, uz straumēm balstīta saskarne datu rakstīšanai failā. Tā ļauj efektīvi rakstīt virknes, Blobus vai buferus un nodrošina metodes, lai pārvietotos uz noteiktu pozīciju vai saīsinātu failu. Lai nodrošinātu, ka izmaiņas tiek ierakstītas diskā, ir jāizsauc tāsclose()metode.
Drošības modelis: uz lietotāju centrēts un drošs
Tiešas piekļuves piešķiršana vietnei jūsu failu sistēmai ir nozīmīgs drošības apsvērums. Šī API izstrādātāji ir izveidojuši spēcīgu, uz atļaujām balstītu drošības modeli, kas prioritizē lietotāja piekrišanu un kontroli.
- Lietotāja iniciētas darbības: Lietojumprogramma nevar spontāni izsaukt failu atlasītāju. Piekļuvei jābūt iniciētai ar tiešu lietotāja žestu, piemēram, pogas klikšķi. Tas novērš ļaundabīgu skriptu klusu jūsu failu sistēmas skenēšanu.
- Atlasītājs ir vārti: API ieejas punkti ir atlasītāja metodes:
window.showOpenFilePicker(),window.showSaveFilePicker()unwindow.showDirectoryPicker(). Šīs metodes parāda pārlūkprogrammas vietējo failu/direktoriju atlases saskarni. Lietotāja izvēle ir skaidra atļaujas piešķiršana konkrētajam elementam. - Atļauju pieprasījumi: Pēc roktura iegūšanas pārlūkprogramma var lūgt lietotājam 'lasīšanas' vai 'lasīšanas-rakstīšanas' atļaujas šim rokturim. Lietotājam ir jāapstiprina šis pieprasījums, pirms lietojumprogramma var turpināt darbu.
- Atļauju noturība: Lai uzlabotu lietotāja pieredzi, pārlūkprogrammas var saglabāt šīs atļaujas noteiktam avotam (vietnei). Tas nozīmē, ka pēc tam, kad lietotājs vienreiz ir piešķīris piekļuvi failam, viņam vairs netiks prasīts to darīt tajā pašā sesijā vai pat nākamajās apmeklējuma reizēs. Atļaujas statusu var pārbaudīt ar
handle.queryPermission()un atkārtoti pieprasīt arhandle.requestPermission(). Lietotāji var jebkurā laikā atsaukt šīs atļaujas, izmantojot savas pārlūkprogrammas iestatījumus. - Tikai drošos kontekstos: Tāpat kā daudzi mūsdienu tīmekļa API, File System Access API ir pieejams tikai drošos kontekstos, kas nozīmē, ka jūsu vietnei jābūt pasniegtai, izmantojot HTTPS vai no localhost.
Šī daudzslāņu pieeja nodrošina, ka lietotājs vienmēr ir informēts un kontrolē situāciju, panākot līdzsvaru starp jaunām, jaudīgām iespējām un nelokāmu drošību.
Praktiska ieviešana: soli pa solim ceļvedis
Pāriesim no teorijas pie prakses. Lūk, kā jūs varat sākt izmantot File System Access API savās tīmekļa lietojumprogrammās. Visas API metodes ir asinhronas un atgriež Promises, tāpēc mēs izmantosim moderno async/await sintaksi tīrākam kodam.
Pārlūkprogrammas atbalsta pārbaude
Pirms API izmantošanas jums ir jāpārbauda, vai lietotāja pārlūkprogramma to atbalsta. Pietiek ar vienkāršu funkcijas noteikšanas pārbaudi.
if ('showOpenFilePicker' in window) {
console.log('Great! The File System Access API is supported.');
} else {
console.log('Sorry, this browser does not support the API.');
// Provide a fallback to <input type="file">
}
Faila lasīšana
Vietējā faila lasīšana ir izplatīts sākumpunkts. Process ietver atvēršanas failu atlasītāja parādīšanu, faila roktura iegūšanu un pēc tam tā satura nolasīšanu.
const openFileButton = document.getElementById('open-file-btn');
openFileButton.addEventListener('click', async () => {
try {
// The showOpenFilePicker() method returns an array of handles,
// but we are only interested in the first one for this example.
const [fileHandle] = await window.showOpenFilePicker();
// Get the File object from the handle.
const file = await fileHandle.getFile();
// Read the file content as text.
const content = await file.text();
// Use the content (e.g., display it in a textarea).
document.getElementById('editor').value = content;
} catch (err) {
// Handle errors, such as the user canceling the picker.
console.error('Error opening file:', err);
}
});
Šajā piemērā window.showOpenFilePicker() atgriež solījumu (promise), kas atrisinās ar FileSystemFileHandle objektu masīvu. Mēs destrukturējam pirmo elementu mūsu fileHandle mainīgajā. No turienes fileHandle.getFile() nodrošina standarta File objektu, kuram ir pazīstamas metodes, piemēram, .text(), .arrayBuffer() un .stream().
Rakstīšana failā
Rakstīšana ir vieta, kur API patiesi spīd, jo tā ļauj gan saglabāt jaunus failus, gan nemanāmi pārrakstīt esošos.
Izmaiņu saglabāšana esošā failā
Paplašināsim mūsu iepriekšējo piemēru. Mums ir jāuzglabā fileHandle, lai mēs to varētu izmantot vēlāk, lai saglabātu izmaiņas.
let currentFileHandle;
// ... inside the 'openFileButton' click listener ...
// After getting the handle from showOpenFilePicker:
currentFileHandle = fileHandle;
// --- Now, set up the save button ---
const saveFileButton = document.getElementById('save-file-btn');
saveFileButton.addEventListener('click', async () => {
if (!currentFileHandle) {
alert('Please open a file first!');
return;
}
try {
// Create a FileSystemWritableFileStream to write to.
const writable = await currentFileHandle.createWritable();
// Get the content from our editor.
const content = document.getElementById('editor').value;
// Write the content to the stream.
await writable.write(content);
// Close the file and write the contents to disk.
// This is a crucial step!
await writable.close();
alert('File saved successfully!');
} catch (err) {
console.error('Error saving file:', err);
}
});
Galvenie soļi ir createWritable(), kas sagatavo failu rakstīšanai, write(), kas nosūta datus, un kritiskais close(), kas pabeidz operāciju un ieraksta izmaiņas diskā.
Jauna faila saglabāšana ('Saglabāt kā')
Lai saglabātu jaunu failu, jūs izmantojat window.showSaveFilePicker(). Tas parāda 'Saglabāt kā' dialoglodziņu un atgriež jaunu FileSystemFileHandle izvēlētajai vietai.
const saveAsButton = document.getElementById('save-as-btn');
saveAsButton.addEventListener('click', async () => {
try {
const newFileHandle = await window.showSaveFilePicker({
suggestedName: 'untitled.txt',
types: [{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
}],
});
// Now we have a handle, we can use the same writing logic as before.
const writable = await newFileHandle.createWritable();
const content = document.getElementById('editor').value;
await writable.write(content);
await writable.close();
// Optionally, update our current handle to this new file.
currentFileHandle = newFileHandle;
alert('File saved to a new location!');
} catch (err) {
console.error('Error saving new file:', err);
}
});
Darbs ar direktorijiem
Spēja strādāt ar veseliem direktorijiem paver jaudīgus lietošanas gadījumus, piemēram, tīmekļa IDE.
Vispirms mēs ļaujam lietotājam izvēlēties direktoriju:
const openDirButton = document.getElementById('open-dir-btn');
openDirButton.addEventListener('click', async () => {
try {
const dirHandle = await window.showDirectoryPicker();
// Now we can process the directory's contents.
await processDirectory(dirHandle);
} catch (err) {
console.error('Error opening directory:', err);
}
});
Kad jums ir FileSystemDirectoryHandle, jūs varat iterēt caur tā saturu, izmantojot asinhronu for...of ciklu. Sekojošā funkcija rekursīvi uzskaita visus failus un apakšdirektorijus.
async function processDirectory(dirHandle) {
const fileListElement = document.getElementById('file-list');
fileListElement.innerHTML = ''; // Clear previous list
for await (const entry of dirHandle.values()) {
const listItem = document.createElement('li');
// The 'kind' property is either 'file' or 'directory'
listItem.textContent = `[${entry.kind}] ${entry.name}`;
fileListElement.appendChild(listItem);
if (entry.kind === 'directory') {
// This shows a simple recursive call is possible,
// though a full UI would handle nesting differently.
console.log(`Found subdirectory: ${entry.name}`);
}
}
}
Jaunu failu un direktoriju izveide
Jūs varat arī programmatiski izveidot jaunus failus un apakšdirektorijus direktorijā, kuram jums ir piekļuve. To dara, nododot { create: true } opciju getFileHandle() vai getDirectoryHandle() metodēm.
async function createNewFile(dirHandle, fileName) {
try {
// Get a handle to a new file, creating it if it doesn't exist.
const newFileHandle = await dirHandle.getFileHandle(fileName, { create: true });
console.log(`Created or got handle for file: ${newFileHandle.name}`);
// You can now write to this handle.
} catch (err) {
console.error('Error creating file:', err);
}
}
async function createNewFolder(dirHandle, folderName) {
try {
// Get a handle to a new directory, creating it if it doesn't exist.
const newDirHandle = await dirHandle.getDirectoryHandle(folderName, { create: true });
console.log(`Created or got handle for directory: ${newDirHandle.name}`);
} catch (err) {
console.error('Error creating directory:', err);
}
}
Progresīvi jēdzieni un lietošanas gadījumi
Kad esat apguvis pamatus, varat izpētīt progresīvākas funkcijas, lai izveidotu patiesi nevainojamu lietotāja pieredzi.
Noturība ar IndexedDB
Liels izaicinājums ir tas, ka FileSystemHandle objekti netiek saglabāti, kad lietotājs atsvaidzina lapu. Lai to atrisinātu, jūs varat saglabāt rokturus IndexedDB, pārlūkprogrammas klienta puses datubāzē. Tas ļauj jūsu lietojumprogrammai atcerēties, ar kādiem failiem un mapēm lietotājs strādāja starp sesijām.
Roktura saglabāšana ir tikpat vienkārša kā tā ievietošana IndexedDB objektu krātuvē. Tā izgūšana ir tikpat viegla. Tomēr atļaujas netiek saglabātas kopā ar rokturi. Kad jūsu lietotne tiek atkārtoti ielādēta un izgūst rokturi no IndexedDB, jums vispirms jāpārbauda, vai jums joprojām ir atļauja, un, ja nepieciešams, tā jāpieprasa atkārtoti.
// Function to retrieve a stored handle
async function getHandleFromDB(key) {
// (Code for opening IndexedDB and getting the handle)
const handle = await getFromDB(key);
if (!handle) return null;
// Check if we still have permission.
if (await handle.queryPermission({ mode: 'readwrite' }) === 'granted') {
return handle; // Permission already granted.
}
// If not, we must request permission again.
if (await handle.requestPermission({ mode: 'readwrite' }) === 'granted') {
return handle; // Permission was granted by the user.
}
// Permission was denied.
return null;
}
Šis modelis ļauj jums izveidot 'Pēdējie faili' vai 'Atvērt neseno projektu' funkciju, kas šķiet gluži kā vietējā lietojumprogrammā.
Vilkt un nomest (Drag and Drop) integrācija
API lieliski integrējas ar vietējo Drag and Drop API. Lietotāji var vilkt failus vai mapes no sava darbvirsmas un nomest tos uz jūsu tīmekļa lietojumprogrammas, lai piešķirtu piekļuvi. To panāk, izmantojot DataTransferItem.getAsFileSystemHandle() metodi.
const dropZone = document.getElementById('drop-zone');
dropZone.addEventListener('dragover', (event) => {
event.preventDefault(); // Necessary to allow dropping
});
dropZone.addEventListener('drop', async (event) => {
event.preventDefault();
for (const item of event.dataTransfer.items) {
if (item.kind === 'file') {
const handle = await item.getAsFileSystemHandle();
if (handle.kind === 'directory') {
console.log(`Directory dropped: ${handle.name}`);
// Process directory handle
} else {
console.log(`File dropped: ${handle.name}`);
// Process file handle
}
}
}
});
Reālās pasaules lietojumprogrammas
Šī API piedāvātās iespējas ir plašas un paredzētas globālai radītāju un profesionāļu auditorijai:
- Tīmekļa IDE un koda redaktori: Rīki, piemēram, VS Code for the Web (vscode.dev), tagad var atvērt lokālu projekta mapi, ļaujot izstrādātājiem rediģēt, izveidot un pārvaldīt visu savu kodu bāzi tieši pārlūkprogrammā.
- Radošie rīki: Attēlu, video un audio redaktori var ielādēt lielus multivides līdzekļus tieši no lietotāja cietā diska, veikt sarežģītas rediģēšanas darbības un saglabāt rezultātu bez lēnā augšupielādes un lejupielādes procesa no servera.
- Produktivitāte un datu analīze: Biznesa lietotājs varētu atvērt lielu CSV vai JSON failu tīmekļa datu vizualizācijas rīkā, analizēt datus un saglabāt pārskatus, un dati nekad neatstātu viņa datoru, kas ir lieliski privātumam un veiktspējai.
- Spēles: Tīmekļa spēles varētu ļaut lietotājiem pārvaldīt saglabātās spēles vai instalēt modifikācijas, piešķirot piekļuvi konkrētai spēles mapei.
Apsvērumi un labākās prakses
Ar lielu varu nāk liela atbildība. Šeit ir daži galvenie apsvērumi izstrādātājiem, kas izmanto šo API.
Koncentrējieties uz lietotāja pieredzi (UX)
- Skaidrība ir galvenais: Vienmēr saistiet API izsaukumus ar skaidrām, nepārprotamām lietotāja darbībām, piemēram, pogām ar uzrakstiem 'Atvērt failu' vai 'Saglabāt izmaiņas'. Nekad nepārsteidziet lietotāju ar failu atlasītāju.
- Sniedziet atgriezenisko saiti: Izmantojiet lietotāja saskarnes elementus, lai informētu lietotāju par operāciju statusu (piemēram, 'Saglabā...', 'Fails veiksmīgi saglabāts', 'Atļauja liegta').
- Eleganti rezerves risinājumi: Tā kā API vēl nav universāli atbalstīts, vienmēr nodrošiniet rezerves mehānismu, izmantojot tradicionālās
<input type="file">un enkura lejupielādes metodes vecākām pārlūkprogrammām.
Veiktspēja
API ir izstrādāts veiktspējai. Novēršot nepieciešamību pēc servera augšupielādes un lejupielādes, lietojumprogrammas var kļūt ievērojami ātrākas, īpaši strādājot ar lieliem failiem. Tā kā visas operācijas ir asinhronas, tās nebloķēs galveno pārlūkprogrammas pavedienu, saglabājot jūsu lietotāja saskarnes atsaucību.
Ierobežojumi un pārlūkprogrammu saderība
Lielākais apsvērums ir pārlūkprogrammu atbalsts. 2023. gada beigās API pilnībā tiek atbalstīts Chromium bāzes pārlūkprogrammās, piemēram, Google Chrome, Microsoft Edge un Opera. Atbalsts Firefox ir izstrādes stadijā aiz karoga, un Safari vēl nav apņēmies to ieviest. Globālai auditorijai tas nozīmē, ka jūs nevarat paļauties uz šo API kā *vienīgo* veidu, kā apstrādāt failus. Vienmēr pārbaudiet uzticamu avotu, piemēram, CanIUse.com, lai iegūtu jaunāko saderības informāciju.
Noslēgums: jauna ēra tīmekļa lietojumprogrammām
File System Access API ir monumentāls solis uz priekšu tīmekļa platformai. Tas tieši risina vienu no nozīmīgākajām funkcionālajām atšķirībām starp tīmekļa un vietējām lietojumprogrammām, dodot izstrādātājiem iespēju veidot jaunu jaudīgu, efektīvu un lietotājam draudzīgu rīku klasi, kas darbojas pilnībā pārlūkprogrammā.
Nodrošinot drošu, lietotāja kontrolētu tiltu uz vietējo failu sistēmu, tas uzlabo lietojumprogrammu iespējas, palielina veiktspēju, samazinot atkarību no serveriem, un racionalizē darba plūsmas lietotājiem visā pasaulē. Lai gan mums ir jābūt uzmanīgiem attiecībā uz pārlūkprogrammu saderību un jāievieš eleganti rezerves risinājumi, ceļš uz priekšu ir skaidrs. Tīmeklis attīstās no platformas satura patērēšanai par nobriedušu platformu tā radīšanai. Mēs aicinām jūs izpētīt File System Access API, eksperimentēt ar tā iespējām un sākt veidot nākamās paaudzes tīmekļa lietojumprogrammas jau šodien.