نظام الملفات الخاصة وأصل

يقدّم "معيار نظام الملفات" نظام ملفات مصدر خاص (OPFS) كنقطة نهاية تخزين خاصة بمصدر الصفحة ولا يمكن للمستخدم الاطّلاع عليه ويوفّر إمكانية الوصول الاختياري إلى نوع خاص من الملفات تم تحسينه بدرجة كبيرة من حيث الأداء.

يتيح نظام الملفات الخاص الأصلي للمتصفّحات الحديثة إمكانية الوصول إلى الملفات، وقد تمّ توحيده من قِبل مجموعة عمل تكنولوجيا تطبيقات النص الفائق على الويب (WHATWG) في معيار نظام الملفات.

دعم المتصفح

  • Chrome: 86
  • ‫Edge: 86
  • Firefox: 111.
  • ‫Safari: 15.2

المصدر

الحافز

عندما تفكر في الملفات على جهاز الكمبيوتر، ربما تفكر في التسلسل الهرمي للملفات: الملفات المنظَّمة في مجلدات يمكنك استكشافها باستخدام مستكشف الملفات في نظام التشغيل. على سبيل المثال، على نظام التشغيل Windows، بالنسبة إلى مستخدم يُدعى تامر، قد تكون قائمة المهام الخاصة به متاحة في C:\Users\Tom\Documents\ToDo.txt. في هذا المثال، يشير ToDo.txt إلى اسم الملف، وUsers وTom وDocuments هي أسماء مجلدات. يمثل `C:` على نظام التشغيل Windows الدليل الجذري لمحرك الأقراص.

الطريقة التقليدية للعمل مع الملفات على الويب

لتعديل قائمة "المهام التي يجب إكمالها" في أحد تطبيقات الويب، اتّبِع الخطوات التالية:

  1. يحمِّل المستخدم الملف إلى خادم أو يفتحه على البرنامج من خلال <input type="file">.
  2. يُجري المستخدم التغييرات، ثم ينزّل الملف الناتج الذي يتضمّن <a download="ToDo.txt> تمّ click() إدراجه آليًا من خلال JavaScript.
  3. لفتح المجلدات، يمكنك استخدام سمة خاصة في <input type="file" webkitdirectory>، والتي تتيح استخدامها في جميع المتصفّحات تقريبًا على الرغم من اسمها الحصري.

طريقة حديثة للعمل مع الملفات على الويب

لا يمثّل هذا المسار طريقة المستخدمين في تعديل الملفات، ويعني ذلك أنّ المستخدمين يحصلون في النهاية على نُسخ تم تنزيلها من ملفات الإدخال. لذلك، قدّمت File System Access API ثلاث طرق لاختيار الملفات، وهي showOpenFilePicker() وshowSaveFilePicker() وshowDirectoryPicker()، وتعمل هذه الطرق على النحو الذي يشير إليه اسمها. ويتم تفعيل هذه العملية على النحو التالي:

  1. افتح ToDo.txt باستخدام showOpenFilePicker()، واحصل على عنصر FileSystemFileHandle.
  2. من عنصر FileSystemFileHandle، احصل على File من خلال استدعاء طريقة getFile() الخاصة بملف المعالجة.
  3. عدِّل الملف، ثم اتصل على requestPermission({mode: 'readwrite'}) باستخدام الاسم المعرِّف.
  4. إذا وافق المستخدم على طلب الإذن، احفظ التغييرات مرة أخرى في الملف الأصلي.
  5. بدلاً من ذلك، يمكنك الاتصال بالرقم showSaveFilePicker() والسماح للمستخدم باختيار ملف جديد. (إذا اختار المستخدم ملفًا تم فتحه مسبقًا، سيتم استبدال محتواه.) بالنسبة إلى عمليات الحفظ المتكررة، يمكنك الاحتفاظ بمقبض الملف، حتى لا تضطر إلى إظهار مربع حوار حفظ الملف مرة أخرى.

قيود العمل مع الملفات على الويب

إنّ الملفات والمجلدات التي يمكن الوصول إليها من خلال هذه الطرق تكون في ما يمكن تسميته بنظام الملفات المرئي للمستخدم. يتم وضع علامة الويب على الملفات المحفوظة من الويب، والملفات القابلة للتنفيذ على وجه التحديد، وذلك لعرض تحذير إضافي يمكن أن يعرضه نظام التشغيل قبل تنفيذ ملف يُحتمل أن يكون خطيرًا. كميزة أمان إضافية، يتم أيضًا حماية الملفات التي يتم الحصول عليها من الويب من خلال ميزة التصفّح الآمن، والتي يمكنك اعتبارها، من أجل التبسيط وفي سياق هذه المقالة، عملية فحص الفيروسات المستندة إلى السحابة الإلكترونية. عند كتابة البيانات في ملف باستخدام واجهة برمجة التطبيقات File System Access API، لا تتم الكتابة في الملف نفسه، بل يتم استخدام ملف مؤقت. ولا يتم تعديل الملف نفسه إلا إذا اجتاز جميع عمليات فحص الأمان هذه. كما يمكنك أن تتخيل، يؤدي هذا العمل إلى إبطاء عمليات الملفات نسبيًا، على الرغم من التحسينات التي تم تطبيقها كلما أمكن ذلك، على سبيل المثال، على نظام التشغيل macOS. لا يزال كل طلب write() مستقلاً بذاته، لذلك يتم فتح الملف بشكل خفي ويبحث عن الإزاحة المحددة، وفي النهاية يكتب البيانات.

الملفات كأساس للمعالجة

وفي الوقت نفسه، تشكّل الملفات طريقة ممتازة لتسجيل البيانات. على سبيل المثال، تخزّن SQLite قواعد بيانات كاملة في ملف واحد. ومن الأمثلة الأخرى الخرائط المنخفضة الدقة المستخدَمة في معالجة الصور. خرائط Mipmap هي تسلسلات محسَّنة من الصور يتم احتسابها مسبقًا، وكل منها يمثّل درجة أقل تدريجيًا من الدقة مقارنةً بالصورة السابقة، ما يجعل العديد من العمليات أسرع، مثل التصغير أو التكبير. كيف يمكن لتطبيقات الويب الاستفادة من مزايا الملفات بدون تكاليف الأداء المرتبطة بمعالجة الملفات المستندة إلى الويب؟ الإجابة هي نظام الملفات الخاص الأصلي.

نظام الملفات الخاص بالمستخدم مقارنةً بنظام الملفات الخاص بالتطبيق الأصلي

على عكس نظام الملفات الظاهر للمستخدم والذي يتم تصفحه باستخدام مستكشف الملفات في نظام التشغيل، لا يمكن للمستخدمين الاطّلاع على نظام الملفات الخاص الأصلي، والذي يتضمّن ملفات ومجلدات يمكنك قراءتها وكتابتها ونقلها وإعادة تسميتها. الملفات والمجلدات في نظام الملفات الخاص بالمصدر، كما يوحي الاسم، تكون خاصة، وبشكل أكثر تحديدًا، تكون خاصة بمصدر الموقع الإلكتروني. تعرَّف على أصل الصفحة من خلال كتابة الرمز location.origin في "وحدة التحكّم في أدوات مطوّري البرامج". على سبيل المثال، مصدر الصفحة https://developer.chrome.com/articles/ هو https://developer.chrome.com (أي أنّ الجزء /articles ليس جزءًا من المصدر). يمكنك الاطّلاع على المزيد من المعلومات حول نظرية الأصول في مقالة فهم طبيعة الموقع الإلكتروني نفسه والمصدر نفسه. يمكن لجميع الصفحات التي تشترك في المصدر نفسه الاطّلاع على بيانات نظام الملفات الخاص بالمستخدم نفسه، وبالتالي يمكن لـ "https://developer.chrome.com/docs/extensions/mv3/getstarted/extensions-101/" الاطّلاع على التفاصيل نفسها الواردة في المثال السابق. ولكل مصدر نظام ملفات خاص مستقل خاص به، ما يعني أنّ نظام الملفات الخاص الأصلي، وهو https://developer.chrome.com، يختلف تمامًا عن نظام https://web.dev. في نظام التشغيل Windows، يكون الدليل الجذري لنظام الملفات المرئي للمستخدم هو C:\\. ويعادل نظام الملف الخاص المصدر هو دليل أساسي فارغ في البداية لكل مصدر يتم الوصول إليه من خلال استدعاء الطريقة غير المتزامنة navigator.storage.getDirectory(). للاطّلاع على مقارنة بين نظام الملفات المرئي للمستخدم ونظام الملفات الخاص الأصلي، راجِع المخطّط البياني التالي. يوضّح المخطّط البياني أنّه باستثناء الدليل الجذر، كل شيء آخر متطابق من الناحية المفاهيمية، مع تسلسل هرمي للملفات والمجلدات لتنظيمها وترتيبها حسب الحاجة لتلبية احتياجات البيانات ومساحة التخزين.

مخطّط بياني لنظام الملفات الظاهر للمستخدم ونظام الملفات الخاص الأصلي مع تسلسلين هرمين مثاليين للملفات نقطة الدخول لنظام الملفات المرئي للمستخدم هي قرص صلب رمزي، ونقطة الدخول لنظام الملفات الخاص الأصلي هي استدعاء الطريقة navigator.storage.getDirectory.

تفاصيل نظام الملفات الخاص الأصلي

تمامًا مثل آليات التخزين الأخرى في المتصفّح (مثل localStorage أو IndexedDB)، يخضع نظام الملفات الخاص الأصلي لقيود مساحة التخزين المتوفّرة في المتصفّح. عندما يُجري المستخدم عملية محو جميع بيانات التصفّح أو جميع بيانات المواقع الإلكترونية، سيتم أيضًا حذف نظام الملفات الخاص الأصلي. يمكنك طلب navigator.storage.estimate() وفي عنصر الاستجابة الناتج، سيظهر الإدخال usage لمعرفة حجم مساحة التخزين التي يستهلكها تطبيقك، والتي يتم تقسيمها حسب آلية التخزين في العنصر usageDetails، حيث تريد الاطّلاع على إدخال fileSystem تحديدًا. بما أنّ نظام الملفات الخاص الأصلي غير مرئي للمستخدم، لا تظهر أي طلبات للحصول على الأذونات ولا يتم إجراء أي عمليات تحقّق من ميزة "التصفّح الآمن".

الحصول على إذن الوصول إلى الدليل الجذري

للوصول إلى الدليل الجذر، نفِّذ الأمر التالي. ينتهي بك الأمر مع مؤشر دليل فارغ، وبشكل أكثر تحديدًا، FileSystemDirectoryHandle.

const opfsRoot = await navigator.storage.getDirectory();
// A FileSystemDirectoryHandle whose type is "directory"
// and whose name is "".
console.log(opfsRoot);

سلسلة التعليمات الرئيسية أو Web Worker

هناك طريقتان لاستخدام نظام الملفات الخاص الأصلي: في سلسلة المحادثات الرئيسية أو في عامل الويب. لا يمكن لخيوط Web Worker حظر سلسلة التعليمات الرئيسية، ما يعني في هذا السياق أنّ واجهات برمجة التطبيقات يمكن أن تكون متزامنة، وهو نمط غير مسموح به بشكل عام في سلسلة التعليمات الرئيسية. يمكن أن تكون واجهات برمجة التطبيقات المتزامنة أسرع لأنّها تتجنّب التعامل مع الوعود، وتكون عمليات الملفات عادةً متزامنة بلغات مثل C التي يمكن تجميعها إلى WebAssembly.

// This is synchronous C code.
FILE *f;
f = fopen("example.txt", "w+");
fputs("Some text\n", f);
fclose(f);

إذا كنت بحاجة إلى أسرع عمليات ممكنة على الملفات، أو كنت تتعامل مع WebAssembly، انتقِل إلى استخدام نظام الملفات الخاص بالمصدر في Web Worker. بخلاف ذلك، يمكنك المتابعة.

استخدام نظام الملفات الخاص الأصلي في سلسلة التعليمات الرئيسية

إنشاء ملفات ومجلدات جديدة

بعد إنشاء مجلد جذر، أنشئ ملفات ومجلدات باستخدام الطريقتَين getFileHandle() وgetDirectoryHandle() على التوالي. عند ضبط القيمة {create: true}، سيتم إنشاء الملف أو المجلد إذا لم يكنا متوفّرين. يمكنك إنشاء تسلسل هرمي للملفات من خلال استدعاء هذه الدوال باستخدام دليل تم إنشاؤه حديثًا كنقطة بداية.

const fileHandle = await opfsRoot
    .getFileHandle('my first file', {create: true});
const directoryHandle = await opfsRoot
    .getDirectoryHandle('my first folder', {create: true});
const nestedFileHandle = await directoryHandle
    .getFileHandle('my first nested file', {create: true});
const nestedDirectoryHandle = await directoryHandle
    .getDirectoryHandle('my first nested folder', {create: true});

التسلسل الهرمي للملف الناتج من نموذج الرمز السابق

الوصول إلى الملفات والمجلدات الحالية

إذا كنت تعرف اسمها، يمكنك الوصول إلى الملفات والمجلدات التي تم إنشاؤها سابقًا من خلال استدعاء الطريقتَين getFileHandle() أو getDirectoryHandle() مع إدخال اسم الملف أو المجلد.

const existingFileHandle = await opfsRoot.getFileHandle('my first file');
const existingDirectoryHandle = await opfsRoot
    .getDirectoryHandle('my first folder');

الحصول على الملف المرتبط بمؤشر الملف للقراءة

يمثّل FileSystemFileHandle ملفًا في نظام الملفات. للحصول على File المرتبط، استخدِم طريقة getFile(). عنصر File هو نوع معيّن من Blob، ويمكن استخدامه في أي سياق يمكن فيه استخدام Blob. على وجه الخصوص، تقبل FileReader وURL.createObjectURL() وcreateImageBitmap() وXMLHttpRequest.send() كلاً من Blobs وFiles. بعبارة أخرى، يؤدي الحصول على File من FileSystemFileHandle إلى "إخلاء" البيانات، ما يتيح لك الوصول إليها وإتاحتها لنظام الملفات المرئي للمستخدم.

const file = await fileHandle.getFile();
console.log(await file.text());

الكتابة في ملف من خلال البث

يمكنك بث البيانات إلى ملف من خلال استدعاء createWritable() الذي ينشئ FileSystemWritableFileStream يمكنك بعد ذلك write() المحتوى. في النهاية، عليك close() البث.

const contents = 'Some text';
// Get a writable stream.
const writable = await fileHandle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the stream, which persists the contents.
await writable.close();

حذف الملفات والمجلدات

يمكنك حذف الملفات والمجلدات من خلال استدعاء طريقة remove() المحددة لملف أو دليل معيّن. لحذف مجلد مع جميع المجلدات الفرعية، مرِّر الخيار {recursive: true}.

await fileHandle.remove();
await directoryHandle.remove({recursive: true});

كخيار بديل، إذا كنت تعرف اسم الملف أو المجلد المطلوب حذفه في دليل، استخدِم طريقة removeEntry().

directoryHandle.removeEntry('my first nested file');

نقل الملفات والمجلدات وإعادة تسميتها

إعادة تسمية الملفات والمجلدات ونقلها باستخدام الطريقة move() يمكن نقل العناصر وإعادة تسميتها معًا أو بشكل منفصل.

// Rename a file.
await fileHandle.move('my first renamed file');
// Move a file to another directory.
await fileHandle.move(nestedDirectoryHandle);
// Move a file to another directory and rename it.
await fileHandle
    .move(nestedDirectoryHandle, 'my first renamed and now nested file');

حلّ مسار ملف أو مجلد

لمعرفة مكان ملف أو مجلد معيّن في ما يتعلق بدليل مرجعي، استخدِم الطريقة resolve() مع تمرير FileSystemHandle كوسيطة. للحصول على المسار الكامل لملف أو مجلد في نظام الملفات الخاص الأصلي، استخدِم الدليل الجذر كدليل مرجعي تم الحصول عليه من خلال navigator.storage.getDirectory().

const relativePath = await opfsRoot.resolve(nestedDirectoryHandle);
// `relativePath` is `['my first folder', 'my first nested folder']`.

التحقّق مما إذا كان اسمان لملف أو مجلد يشيرَان إلى الملف أو المجلد نفسه

في بعض الأحيان، يكون لديك اسمان معرِّفان ولا تعرف ما إذا كانا يشيرَين إلى الملف أو المجلد نفسه. لمعرفة ما إذا كان الأمر كذلك، استخدِم الطريقة isSameEntry().

fileHandle.isSameEntry(nestedFileHandle);
// Returns `false`.

إدراج محتوى مجلد

FileSystemDirectoryHandle هو عاكس خطوات غير متزامن يمكنك تكراره باستخدام حلقة for await…of. وبصفتها أداة تكرار غير متزامنة، تتيح هذه الطريقة أيضًا استخدام طرق entries() وvalues() وkeys()، ويمكنك الاختيار من بينها حسب المعلومات التي تحتاجها:

for await (let [name, handle] of directoryHandle) {}
for await (let [name, handle] of directoryHandle.entries()) {}
for await (let handle of directoryHandle.values()) {}
for await (let name of directoryHandle.keys()) {}

إدراج محتوى المجلد وجميع المجلدات الفرعية بشكل متكرر

من السهل حدوث خطأ في التعامل مع التكرارات غير المتزامنة والدوال المرتبطة بالتكرار. يمكن أن تُستخدم الدالة أدناه كنقطة بداية لعرض محتويات مجلد وكل المجلدات الفرعية له، بما في ذلك جميع الملفات وأحجامها. يمكنك تبسيط الدالة إذا لم تكن بحاجة إلى أحجام الملفات، حيث يظهر directoryEntryPromises.push، وليس handle.getFile()، ولكن handle مباشرةً.

  const getDirectoryEntriesRecursive = async (
    directoryHandle,
    relativePath = '.',
  ) => {
    const fileHandles = [];
    const directoryHandles = [];
    const entries = {};
    // Get an iterator of the files and folders in the directory.
    const directoryIterator = directoryHandle.values();
    const directoryEntryPromises = [];
    for await (const handle of directoryIterator) {
      const nestedPath = `${relativePath}/${handle.name}`;
      if (handle.kind === 'file') {
        fileHandles.push({ handle, nestedPath });
        directoryEntryPromises.push(
          handle.getFile().then((file) => {
            return {
              name: handle.name,
              kind: handle.kind,
              size: file.size,
              type: file.type,
              lastModified: file.lastModified,
              relativePath: nestedPath,
              handle
            };
          }),
        );
      } else if (handle.kind === 'directory') {
        directoryHandles.push({ handle, nestedPath });
        directoryEntryPromises.push(
          (async () => {
            return {
              name: handle.name,
              kind: handle.kind,
              relativePath: nestedPath,
              entries:
                  await getDirectoryEntriesRecursive(handle, nestedPath),
              handle,
            };
          })(),
        );
      }
    }
    const directoryEntries = await Promise.all(directoryEntryPromises);
    directoryEntries.forEach((directoryEntry) => {
      entries[directoryEntry.name] = directoryEntry;
    });
    return entries;
  };

استخدام نظام الملفات الخاص بالتطبيق الأصلي في Web Worker

كما هو موضّح سابقًا، لا يمكن لخيوط Web Worker حظر سلسلة المهام الرئيسية، ولهذا السبب يُسمح باستخدام الطرق المتزامنة في هذا السياق.

الحصول على مؤشر وصول متزامن

نقطة الدخول إلى أسرع عمليات ممكنة على الملفات هي FileSystemSyncAccessHandle، ويتم الحصول عليها من FileSystemFileHandle العادي من خلال استدعاء createSyncAccessHandle().

const fileHandle = await opfsRoot
    .getFileHandle('my highspeed file.txt', {create: true});
const syncAccessHandle = await fileHandle.createSyncAccessHandle();

طرق الملفات المتزامنة في مكانها

بعد الحصول على معرّف وصول متزامن، يمكنك الوصول إلى طرق الملفات السريعة التي تتم بشكل متزامن.

  • getSize(): عرض حجم الملف بالبايت
  • write(): تُسجِّل محتوى المخزن المؤقت في الملف، اختياريًا عند إزاحة معيّنة، وتُعرِض عدد البايتات المكتوبة. يتيح التحقّق من العدد المعروض من وحدات البايت التي تمّ كتابتها للمتصلين رصد الأخطاء والعمليات غير المكتملة للكتابة ومعالجتها.
  • read(): لقراءة محتوى الملف في مخزن مؤقت، اختياريًا عند إزاحة معيّنة
  • truncate(): تغيير حجم الملف إلى الحجم المحدَّد
  • flush(): يضمن أنّ محتوى الملف يحتوي على جميع التعديلات التي تم إجراؤها من خلال write().
  • close(): لإغلاق معرّف الوصول

في ما يلي مثال يستخدم جميع الطرق المذكورة أعلاه.

const opfsRoot = await navigator.storage.getDirectory();
const fileHandle = await opfsRoot.getFileHandle('fast', {create: true});
const accessHandle = await fileHandle.createSyncAccessHandle();

const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();

// Initialize this variable for the size of the file.
let size;
// The current size of the file, initially `0`.
size = accessHandle.getSize();
// Encode content to write to the file.
const content = textEncoder.encode('Some text');
// Write the content at the beginning of the file.
accessHandle.write(content, {at: size});
// Flush the changes.
accessHandle.flush();
// The current size of the file, now `9` (the length of "Some text").
size = accessHandle.getSize();

// Encode more content to write to the file.
const moreContent = textEncoder.encode('More content');
// Write the content at the end of the file.
accessHandle.write(moreContent, {at: size});
// Flush the changes.
accessHandle.flush();
// The current size of the file, now `21` (the length of
// "Some textMore content").
size = accessHandle.getSize();

// Prepare a data view of the length of the file.
const dataView = new DataView(new ArrayBuffer(size));

// Read the entire file into the data view.
accessHandle.read(dataView);
// Logs `"Some textMore content"`.
console.log(textDecoder.decode(dataView));

// Read starting at offset 9 into the data view.
accessHandle.read(dataView, {at: 9});
// Logs `"More content"`.
console.log(textDecoder.decode(dataView));

// Truncate the file after 4 bytes.
accessHandle.truncate(4);

نسخ ملف من نظام الملفات الخاص المصدر إلى نظام الملفات المرئي للمستخدم

كما ذكرنا أعلاه، لا يمكن نقل الملفات من نظام الملفات الخاص الأصلي إلى نظام الملفات المرئية للمستخدم، ولكن يمكنك نسخ الملفات. بما أنّ showSaveFilePicker() لا يظهر إلا في سلسلة التعليمات الرئيسية، وليس في سلسلة التعليمات العاملة، احرص على تشغيل الرمز البرمجي هناك.

// On the main thread, not in the Worker. This assumes
// `fileHandle` is the `FileSystemFileHandle` you obtained
// the `FileSystemSyncAccessHandle` from in the Worker
// thread. Be sure to close the file in the Worker thread first.
const fileHandle = await opfsRoot.getFileHandle('fast');
try {
  // Obtain a file handle to a new file in the user-visible file system
  // with the same name as the file in the origin private file system.
  const saveHandle = await showSaveFilePicker({
    suggestedName: fileHandle.name || ''
  });
  const writable = await saveHandle.createWritable();
  await writable.write(await fileHandle.getFile());
  await writable.close();
} catch (err) {
  console.error(err.name, err.message);
}

تصحيح أخطاء نظام الملفات الخاص الأصلي

إلى أن تتم إضافة أدوات مطوري البرامج المدمجة (راجِع crbug/1284595)، استخدِم إضافة مستكشف نظام الملفات الخاص (OPFS) في Chrome لتصحيح أخطاء نظام الملفات الخاص الأصلي. تم الحصول على لقطة الشاشة أعلاه من قسم إنشاء ملفات ومجلدات جديدة مباشرةً من الإضافة.

إضافة OPFS Explorer في &quot;أدوات مطوّري البرامج في Chrome&quot; في &quot;سوق Chrome الإلكتروني&quot;

بعد تثبيت الإضافة، افتح "أدوات مطوّري البرامج في Chrome"، واختَر علامة التبويب مستكشف نظام الملفات المفتوح (OPFS)، وسيكون بإمكانك بعد ذلك فحص التسلسل الهرمي للملفات. يمكنك حفظ الملفات من نظام الملفات الخاص الأصلي في نظام الملفات الظاهر للمستخدم من خلال النقر على اسم الملف وحذف الملفات والمجلدات من خلال النقر على رمز سلة المهملات.

عرض توضيحي

يمكنك الاطّلاع على نظام الملفات الخاص المصدر قيد التشغيل (في حال تثبيت إضافة OPFS Explorer) في عرض توضيحي تستخدمه كخلفية لقاعدة بيانات SQLite تم تجميعها في WebAssembly. احرص على الاطّلاع على رمز المصدر على Glitch. يُرجى ملاحظة أنّ الإصدار المضمّن أدناه لا يستخدم الخلفية الخاصة بنظام الملفات الخاص بالمصدر (لأنّ عنصر iframe متعدد المصادر)، ولكنّه يستخدمها عند فتح العرض الترويجي في علامة تبويب منفصلة.

الاستنتاجات

لقد حدّد معيار WHATWG نظام الملفات الخاص الأصلي، ما ساهم في تحديد طريقة استخدامنا للملفات والتفاعل معها على الويب. وقد سمح هذا الإجراء بحالات استخدام جديدة كان من المستحيل تحقيقها باستخدام نظام الملفات المرئي للمستخدم. وقد انضمّ جميع مورّدي المتصفّحات الرئيسيين، وهم Apple وMozilla وGoogle، إلى هذه المبادرة ويتشاركون رؤيتها المشتركة. يعتمد تطوير نظام الملفات الخاص الأصلي على جهود تعاونية، وتعد الملاحظات الواردة من المطوّرين والمستخدمين ضرورية لتطويره. بينما نواصل تحسين المعيار، نرحّب بملاحظاتك حول مستودع whatwg/fs في شكل مشاكل أو طلبات سحب.

الشكر والتقدير

راجع هذه المقالة كلّ من أوستن سولي وإتيان نويل وراشيل أندرو. الصورة الرئيسية تقدّمها كريستينا رامف على Unsplash.