ब्राउज़र-fs-access लाइब्रेरी की मदद से, फ़ाइलें और डायरेक्ट्री पढ़ना और लिखना

ब्राउज़र लंबे समय से फ़ाइलों और डायरेक्ट्री पर काम कर सकते हैं. File API वेब ऐप्लिकेशन में फ़ाइल ऑब्जेक्ट को दिखाने के लिए सुविधाएं देता है, उन्हें प्रोग्राम के हिसाब से चुनकर उनका डेटा ऐक्सेस करें. हालांकि, जब आप पास देखते हैं, तो हर ग्लिटर सोने की वजह नहीं होती.

फ़ाइलों से निपटने का पारंपरिक तरीका

फ़ाइलें खोलना

डेवलपर के रूप में, आप <input type="file"> एलिमेंट. अपने सबसे आसान रूप में, किसी फ़ाइल को खोलने पर वह कुछ नीचे दिए गए कोड सैंपल की तरह दिख सकती है. input ऑब्जेक्ट, आपको FileList देता है, इस मामले में, इसमें सिर्फ़ एक शामिल है. File. File एक खास तरह का Blob है, इसे किसी भी कॉन्टेक्स्ट में इस्तेमाल किया जा सकता है.

const openFile = async () => {
  return new Promise((resolve) => {
    const input = document.createElement('input');
    input.type = 'file';
    input.addEventListener('change', () => {
      resolve(input.files[0]);
    });
    input.click();
  });
};

डायरेक्ट्री खुल रही हैं

फ़ोल्डर (या डायरेक्ट्री) खोलने के लिए, आप <input webkitdirectory> एट्रिब्यूट की वैल्यू सबमिट करें. इसके अलावा, बाकी सब कुछ ऊपर की तरह ही काम करता है. वेंडर का प्रीफ़िक्स नाम होने के बावजूद, webkitdirectory का इस्तेमाल सिर्फ़ Chromium और WebKit ब्राउज़र में ही नहीं किया जा सकता. साथ ही, इसका इस्तेमाल लेगसी EdgeHTML पर आधारित Edge और Firefox में भी किया जा सकता है.

फ़ाइलें सेव करने के बजाय: डाउनलोड की जा रही हैं

आम तौर पर, किसी फ़ाइल को सेव करने के लिए, उसे डाउनलोड किया जा सकता है, इस टूल की मदद से, यह काम <a download> एट्रिब्यूट की वैल्यू सबमिट करें. ब्लॉब को देखते हुए, आपके पास ऐंकर के href एट्रिब्यूट को blob: यूआरएल पर सेट करने का विकल्प है. ऐसा करने से, आपको यह यूआरएल मिल सकता है: URL.createObjectURL() तरीका.

const saveFile = async (blob) => {
  const a = document.createElement('a');
  a.download = 'my-file.txt';
  a.href = URL.createObjectURL(blob);
  a.addEventListener('click', (e) => {
    setTimeout(() => URL.revokeObjectURL(a.href), 30 * 1000);
  });
  a.click();
};

समस्या

डाउनलोड करने के तरीके का एक बड़ा नुकसान यह है कि क्लासिक वर्शन बनाने का कोई तरीका नहीं है. खोलें→बदलाव करें→सेव करें, फ़्लो जनरेट होता है. इसका मतलब है कि ओरिजनल फ़ाइल को ओवरराइट करने का कोई तरीका नहीं है. इसके बजाय, आपको ओरिजनल फ़ाइल की एक नई कॉपी देनी होती है ऑपरेटिंग सिस्टम के डिफ़ॉल्ट डाउनलोड फ़ोल्डर में सेव करें.

फ़ाइल सिस्टम ऐक्सेस एपीआई

File System Access API, कार्रवाइयों को खोलने और सेव करने, दोनों को बहुत आसान बनाती है. इससे सही तरीके से सेव करने की सुविधा भी चालू हो जाती है. इसका मतलब है कि आपके पास न सिर्फ़ यह चुनने का विकल्प होता है कि फ़ाइल को कहां सेव करना है, लेकिन मौजूदा फ़ाइल को भी ओवरराइट कर दें.

फ़ाइलें खोलना

File System Access API का इस्तेमाल करके, किसी फ़ाइल को खोलना, window.showOpenFilePicker() विधि को कॉल करने का मामला है. यह कॉल एक फ़ाइल हैंडल लौटाता है, जिससे आप getFile() विधि के ज़रिए वास्तविक File पा सकते हैं.

const openFile = async () => {
  try {
    // Always returns an array.
    const [handle] = await window.showOpenFilePicker();
    return handle.getFile();
  } catch (err) {
    console.error(err.name, err.message);
  }
};

डायरेक्ट्री खुल रही हैं

कॉल करके डायरेक्ट्री खोलें window.showDirectoryPicker(), जो फ़ाइल डायलॉग बॉक्स में डायरेक्ट्री को चुना जा सकता है.

फ़ाइलें सेव की जा रही हैं

फ़ाइलों को सेव करना भी इसी तरह आसान है. किसी फ़ाइल हैंडल से, createWritable() के ज़रिए लिखने लायक स्ट्रीम बनाई जाती है, इसके बाद, स्ट्रीम के write() तरीके को कॉल करके Blob डेटा लिखा जाएगा, और अंत में आप स्ट्रीम की close() विधि को कॉल करके बंद कर देते हैं.

const saveFile = async (blob) => {
  try {
    const handle = await window.showSaveFilePicker({
      types: [{
        accept: {
          // Omitted
        },
      }],
    });
    const writable = await handle.createWritable();
    await writable.write(blob);
    await writable.close();
    return handle;
  } catch (err) {
    console.error(err.name, err.message);
  }
};

पेश है ब्राउज़र-एफ़एस-ऐक्सेस

File System Access API की मदद से, यह भरोसा करें कि यह अभी तक ज़्यादा लोगों के लिए उपलब्ध नहीं है.

File System Access API के लिए, ब्राउज़र सहायता टेबल. सभी ब्राउज़र &#39;कोई सहायता नहीं&#39; के तौर पर मार्क किए गए हैं या &#39;फ़्लैग के पीछे&#39; रखें.
File System Access API के लिए, ब्राउज़र सहायता टेबल. (सोर्स)

यही वजह है कि मुझे File System Access API, प्रोग्रेसिव एन्हैंसमेंट की तरह दिखता है. मैं इसका इस्तेमाल तब करना चाहता/चाहती हूं, जब ब्राउज़र पर यह सुविधा काम करती हो, और अगर ऐसा नहीं होता है, तो पारंपरिक तरीके का इस्तेमाल करें; साथ ही, काम न करने वाले JavaScript कोड को बेवजह डाउनलोड करने की ज़रूरत नहीं पड़ती. browser-fs-access इस चैलेंज का जवाब लाइब्रेरी है.

डिज़ाइन फ़िलॉसफ़ी

हालांकि, आने वाले समय में File System Access API में बदलाव हो सकता है, इसलिए ब्राउज़र-एफ़एस-ऐक्सेस एपीआई को इसके बाद मॉडल नहीं किया जाता है. इसका मतलब है कि लाइब्रेरी, पॉलीफ़िल नहीं है, बल्कि पोनीफ़िल का इस्तेमाल करें. अपने ऐप्लिकेशन को जितना हो सके छोटा रखने के लिए किसी भी फ़ंक्शन को खास तौर पर इंपोर्ट किया जा सकता है. उपलब्ध तरीकों को सही नाम दिया गया है fileOpen() directoryOpen(), और fileSave(). अंदरूनी तौर पर, लाइब्रेरी की सुविधा यह पता लगाती है कि क्या File System Access API काम करता है, और फिर संबंधित कोड पाथ को इंपोर्ट करता है.

ब्राउज़र-एफ़एस-ऐक्सेस लाइब्रेरी का इस्तेमाल करना

तीनों तरीके इस्तेमाल में आसान हैं. आपके पास यह तय करने का विकल्प होता है कि आपका ऐप्लिकेशन किस mimeTypes या फ़ाइल extensions को स्वीकार करे. साथ ही, multiple फ़्लैग भी सेट किया जा सकता है एक से ज़्यादा फ़ाइलों या डायरेक्ट्री को चुनने की अनुमति देने या न देने के लिए. पूरी जानकारी के लिए, यह देखें browser-fs-access API दस्तावेज़. नीचे दिए गए कोड सैंपल में, इमेज फ़ाइलों को खोलने और सेव करने का तरीका बताया गया है.

// The imported methods will use the File
// System Access API or a fallback implementation.
import {
  fileOpen,
  directoryOpen,
  fileSave,
} from 'https://unpkg.com/browser-fs-access';

(async () => {
  // Open an image file.
  const blob = await fileOpen({
    mimeTypes: ['image/*'],
  });

  // Open multiple image files.
  const blobs = await fileOpen({
    mimeTypes: ['image/*'],
    multiple: true,
  });

  // Open all files in a directory,
  // recursively including subdirectories.
  const blobsInDirectory = await directoryOpen({
    recursive: true
  });

  // Save a file.
  await fileSave(blob, {
    fileName: 'Untitled.png',
  });
})();

डेमो

ऊपर दिए गए कोड को Glitch के डेमो में काम करते हुए देखा जा सकता है. इसका सोर्स कोड भी वहां उपलब्ध है. सुरक्षा की वजहों से, क्रॉस ऑरिजिन सब फ़्रेम को फ़ाइल पिकर दिखाने की अनुमति नहीं है, इस लेख में डेमो को एम्बेड नहीं किया जा सकता.

जंगल में ब्राउज़र-एफ़एस-ऐक्सेस लाइब्रेरी

अपने खाली समय में, मैं इंस्टॉल किया जा सकने वाला PWA इसे एक्कैलिड्रा कहा जाता है. एक व्हाइटबोर्ड टूल है, जिसकी मदद से आप हाथ से बने चित्र का इस्तेमाल करके आसानी से स्केच बना सकते हैं. यह पूरी तरह से रिस्पॉन्सिव है और छोटे मोबाइल फ़ोन से लेकर बड़ी स्क्रीन वाले कंप्यूटर तक, कई तरह के डिवाइसों पर अच्छी तरह से काम करता है. इसका मतलब है कि इसे सभी अलग-अलग प्लैटफ़ॉर्म पर मौजूद फ़ाइलों पर काम करना होगा वे फ़ाइल सिस्टम ऐक्सेस एपीआई के साथ काम करते हैं या नहीं. इससे यह ब्राउज़र-एफ़एस-ऐक्सेस लाइब्रेरी के लिए एक बेहतरीन कैंडिडेट बन जाता है.

उदाहरण के लिए, मैं अपने iPhone पर ड्रॉइंग बना सकता/सकती हूं, इसे सेव करें (तकनीकी रूप से: इसे डाउनलोड करें, क्योंकि Safari, File System Access API पर काम नहीं करता) मेरे iPhone के डाउनलोड फ़ोल्डर में, फ़ाइल को मेरे डेस्कटॉप पर खोलें (मेरे फ़ोन से ट्रांसफ़र करने के बाद), फ़ाइल को संशोधित कर सकता है, और इसे मेरे द्वारा किए गए परिवर्तनों के साथ अधिलेखित कर सकता है, या यहां तक कि उसे एक नई फ़ाइल के रूप में भी सहेज सकता है.

iPhone पर एक Excalidraw ड्रॉइंग बनाई हुई है.
किसी iPhone पर Excalidraw ड्रॉइंग शुरू करना, जहां File System Access API काम नहीं करता हो. हालांकि, जहां किसी फ़ाइल को डाउनलोड फ़ोल्डर में सेव (डाउनलोड) किया जा सकता हो.
डेस्कटॉप पर, Chrome पर Excalidraw ड्रॉइंग बनाई गई है.
Excalidraw ड्रॉइंग को डेस्कटॉप पर खोलना और उसमें बदलाव करना, जहां File System Access API काम करता है. इससे फ़ाइल को एपीआई के ज़रिए ऐक्सेस किया जा सकता है.
ओरिजनल फ़ाइल को बदलावों के साथ ओवरराइट करना.
मूल फ़ाइल को, मूल Excalidraw ड्रॉइंग फ़ाइल में किए गए बदलावों के साथ ओवरराइट करें. ब्राउज़र पर एक डायलॉग दिखता है, जिसमें पूछा जाता है कि यह ठीक है या नहीं.
बदलावों को एक नई Excalidraw ड्रॉइंग फ़ाइल में सेव किया जा रहा है.
बदलावों को एक नई Excalidraw फ़ाइल में सेव किया जा रहा है. ओरिजनल फ़ाइल पर कोई कार्रवाई नहीं की जाती.

रीयल लाइफ़ कोड सैंपल

नीचे ब्राउज़र-fs-ऐक्सेस का एक उदाहरण दिया गया है, क्योंकि इसका इस्तेमाल Excalidraw में किया जाता है. यह उद्धरण यहां से लिया गया है: /src/data/json.ts. खास बात यह है कि saveAsJSON() तरीका, फ़ाइल हैंडल या null को ब्राउज़र-fs-ऐक्सेस के लिए कैसे पास करता है fileSave() तरीका दिया जाता है, जिसकी वजह से हैंडल दिए जाने पर यह ओवरराइट हो जाता है, या अगर नहीं किया है, तो किसी नई फ़ाइल में सेव करने के लिए.

export const saveAsJSON = async (
  elements: readonly ExcalidrawElement[],
  appState: AppState,
  fileHandle: any,
) => {
  const serialized = serializeAsJSON(elements, appState);
  const blob = new Blob([serialized], {
    type: "application/json",
  });
  const name = `${appState.name}.excalidraw`;
  (window as any).handle = await fileSave(
    blob,
    {
      fileName: name,
      description: "Excalidraw file",
      extensions: ["excalidraw"],
    },
    fileHandle || null,
  );
};

export const loadFromJSON = async () => {
  const blob = await fileOpen({
    description: "Excalidraw files",
    extensions: ["json", "excalidraw"],
    mimeTypes: ["application/json"],
  });
  return loadFromBlob(blob);
};

यूज़र इंटरफ़ेस (यूआई) पर ध्यान दें

चाहे आप Excalidraw पर हों या आपके ऐप्लिकेशन में, यूज़र इंटरफ़ेस (यूआई), ब्राउज़र की सहायता स्थिति के हिसाब से होना चाहिए. अगर File System Access API काम करता है (if ('showOpenFilePicker' in window) {}) आपके पास सेव करें बटन के साथ-साथ, इस रूप में सेव करें बटन दिखाने का विकल्प होता है. नीचे दिए गए स्क्रीनशॉट, iPhone और Chrome डेस्कटॉप पर Excalidraw के मुख्य ऐप्लिकेशन टूलबार के बीच का अंतर दिखाते हैं. ध्यान दें कि iPhone पर इस रूप में सेव करें बटन मौजूद नहीं है.

iPhone पर बस &#39;सेव करें&#39; से Excalidraw ऐप्लिकेशन टूलबार बटन.
iPhone पर सिर्फ़ सेव करें बटन से Excalidraw ऐप्लिकेशन टूलबार बनाया जा सकता है.
Chrome डेस्कटॉप पर &#39;सेव करें&#39; के साथ Excalidraw ऐप्लिकेशन टूलबार और &#39;इस रूप में सेव करें&#39; बटन.
Chrome पर Excalidraw ऐप्लिकेशन टूलबार, सेव करें और फ़ोकस किए गए इस रूप में सेव करें बटन के साथ.

मीटिंग में सामने आए नतीजे

सिस्टम फ़ाइलों के साथ काम करना, तकनीकी रूप से सभी मॉडर्न ब्राउज़र पर काम करता है. फ़ाइल सिस्टम ऐक्सेस एपीआई के साथ काम करने वाले ब्राउज़र पर, फ़ाइलों को ऐक्सेस करने की अनुमति देकर फ़ाइलों को सेव और ओवरराइट करने (न सिर्फ़ डाउनलोड करने) के लिए, और जिससे उपयोगकर्ता जहां चाहें, नई फ़ाइलें बना सकते हैं. यह सुविधा, File System Access API का इस्तेमाल न करने वाले ब्राउज़र पर काम करती है. browser-fs-access आपके काम को आसान बनाता है वे प्रोग्राम को आगे बढ़ाने की हर सुविधा का इस्तेमाल कर सकते हैं. साथ ही, अपने कोड को जितना हो सके उतना आसान बना सकते हैं.

स्वीकार की गई

इस लेख की समीक्षा जो मेडली ने की है और कायस बास्क. Excalidraw में योगदान देने वालों को धन्यवाद और पुल के अनुरोधों की समीक्षा करने के लिए किया. हीरो इमेज: Unस्प्लैश पर इलिया पावलोव.