JavaScript में फ़ाइलें पढ़ना

उपयोगकर्ता के लोकल डिवाइस पर फ़ाइलों को चुनना और उनसे इंटरैक्ट करना, वेब की सबसे ज़्यादा इस्तेमाल की जाने वाली सुविधाओं में से एक है. यह उपयोगकर्ताओं को फ़ाइलें चुनने और उन्हें सर्वर पर अपलोड करने की सुविधा देता है. उदाहरण के लिए, फ़ोटो शेयर करते समय या टैक्स के दस्तावेज़ सबमिट करते समय. यह साइटों को पूरे नेटवर्क पर डेटा ट्रांसफ़र किए बिना ही उन्हें पढ़ने और उनमें बदलाव करने की अनुमति भी देता है. इस पेज पर बताया गया है कि फ़ाइलों से इंटरैक्ट करने के लिए, JavaScript का इस्तेमाल कैसे किया जाता है.

आधुनिक File System Access API

File System Access API, उपयोगकर्ता के लोकल सिस्टम पर मौजूद फ़ाइलों और डायरेक्ट्री को पढ़ने और उनमें लिखने की सुविधा देता है. यह Chromium और Edge जैसे ज़्यादातर Chromium-आधारित ब्राउज़र में उपलब्ध है. इसके बारे में ज़्यादा जानने के लिए, File System Access API पर जाएं.

File System Access API, सभी ब्राउज़र पर काम नहीं करता है. इसलिए, हमारा सुझाव है कि आप Browser-fs-access का इस्तेमाल करें. यह एक हेल्पर लाइब्रेरी है, जो उपलब्ध न होने पर पुराने तरीकों का इस्तेमाल करती है.

फ़ाइलों के साथ काम करें, यह एक क्लासिक तरीका है

इस गाइड में, JavaScript के पुराने तरीकों का इस्तेमाल करके फ़ाइलों के साथ इंटरैक्ट करने का तरीका बताया गया है.

फ़ाइलें चुनें

फ़ाइलें चुनने के दो मुख्य तरीके हैं: एचटीएमएल इनपुट एलिमेंट का इस्तेमाल करना और ड्रैग-एंड-ड्रॉप ज़ोन का इस्तेमाल करना.

एचटीएमएल इनपुट एलिमेंट

उपयोगकर्ताओं के लिए फ़ाइलों को चुनने का सबसे आसान तरीका <input type="file"> एलिमेंट का इस्तेमाल करना है, जो हर बड़े ब्राउज़र में काम करता है. क्लिक करने पर, यह उपयोगकर्ता को एक फ़ाइल या एक से ज़्यादा फ़ाइलें चुनने की सुविधा देता है. हालांकि, इसके लिए ज़रूरी है कि multiple एट्रिब्यूट को उनके ऑपरेटिंग सिस्टम में पहले से मौजूद फ़ाइल चुनने के यूज़र इंटरफ़ेस (यूआई) का इस्तेमाल करके शामिल किया गया हो. जब उपयोगकर्ता कोई फ़ाइल या फ़ाइलें चुन लेता है, तो एलिमेंट का change इवेंट ट्रिगर हो जाता है. event.target.files से फ़ाइलों की सूची ऐक्सेस की जा सकती है, जो एक FileList ऑब्जेक्ट है. FileList का हर आइटम एक File ऑब्जेक्ट है.

<!-- The `multiple` attribute lets users select multiple files. -->
<input type="file" id="file-selector" multiple>
<script>
  const fileSelector = document.getElementById('file-selector');
  fileSelector.addEventListener('change', (event) => {
    const fileList = event.target.files;
    console.log(fileList);
  });
</script>

इस उदाहरण में, उपयोगकर्ता अपने ऑपरेटिंग सिस्टम में पहले से मौजूद फ़ाइल चुनने के यूज़र इंटरफ़ेस (यूआई) का इस्तेमाल करके कई फ़ाइलें चुन सकता है. इसके बाद, चुनी गई हर फ़ाइल को कंसोल में लॉग करता है.

उन फ़ाइलों को सीमित करें जिन्हें उपयोगकर्ता चुन सकते हैं

कुछ मामलों में, आप उपयोगकर्ताओं की ओर से चुनी जा सकने वाली फ़ाइलों के प्रकार को सीमित कर सकते हैं. उदाहरण के लिए, इमेज एडिटिंग ऐप्लिकेशन को सिर्फ़ इमेज स्वीकार करनी चाहिए, टेक्स्ट फ़ाइलें नहीं. फ़ाइल टाइप से जुड़ी पाबंदियां सेट करने के लिए, इनपुट एलिमेंट में accept एट्रिब्यूट जोड़ें. इससे यह तय किया जा सकेगा कि किस तरह की फ़ाइल स्वीकार की जाती है:

<input type="file" id="file-selector" accept=".jpg, .jpeg, .png">

पसंद के मुताबिक खींचें और छोड़ें

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

ड्रॉप ज़ोन चुनें

आपके ऐप्लिकेशन के डिज़ाइन के हिसाब से, आपके प्रॉडक्ट को लॉन्च करने की जगह तय की जाती है. ऐसा हो सकता है कि आप विंडो का सिर्फ़ एक हिस्सा नीचे की ओर ले जाना चाहें, लेकिन पूरी विंडो का इस्तेमाल किया जा सकता है.

Squoosh का स्क्रीनशॉट, जो इमेज कंप्रेस करने वाला वेब ऐप्लिकेशन है.
Squoosh, पूरी विंडो को एक ड्रॉप ज़ोन बना देता है.

इमेज कंप्रेस करने वाले ऐप्लिकेशन Squoosh की मदद से, उपयोगकर्ता किसी इमेज को विंडो में कहीं भी खींचकर ले जा सकते हैं. साथ ही, <input type="file"> एलिमेंट शुरू करने के लिए, इमेज चुनें पर क्लिक करें. ड्रॉप ज़ोन के तौर पर भले ही कोई भी विकल्प चुनें, लेकिन पक्का करें कि उपयोगकर्ता को साफ़ तौर पर बताया गया हो कि वे फ़ाइलों को खींचकर उस प्लैटफ़ॉर्म पर ले जा सकते हैं.

ड्रॉप ज़ोन तय करें

किसी एलिमेंट को खींचें और छोड़ें ज़ोन के तौर पर चालू करने के लिए, इन दो इवेंट के लिए लिसनर बनाएं: dragover और drop. dragover इवेंट, ब्राउज़र के यूज़र इंटरफ़ेस को अपडेट करता है, ताकि यह दिखाया जा सके कि 'खींचें और छोड़ें' ऐक्शन से फ़ाइल की कॉपी बन रही है. जब उपयोगकर्ता फ़ाइलों को प्लैटफ़ॉर्म पर डालता है, तब drop इवेंट ट्रिगर होता है. इनपुट एलिमेंट की तरह, event.dataTransfer.files की फ़ाइलों की सूची को ऐक्सेस किया जा सकता है, जो एक FileList ऑब्जेक्ट है. FileList का हर आइटम, एक File ऑब्जेक्ट है.

const dropArea = document.getElementById('drop-area');

dropArea.addEventListener('dragover', (event) => {
  event.stopPropagation();
  event.preventDefault();
  // Style the drag-and-drop as a "copy file" operation.
  event.dataTransfer.dropEffect = 'copy';
});

dropArea.addEventListener('drop', (event) => {
  event.stopPropagation();
  event.preventDefault();
  const fileList = event.dataTransfer.files;
  console.log(fileList);
});

event.stopPropagation() और event.preventDefault() ब्राउज़र का डिफ़ॉल्ट व्यवहार रोकें और उसके बजाय अपने कोड को चलने दें. उनके बिना, ब्राउज़र आपके पेज से बाहर चला जाएगा और उन फ़ाइलों को खोलेगा जिन्हें उपयोगकर्ता ने ब्राउज़र विंडो में छोड़ा था.

लाइव डेमो देखने के लिए, पसंद के मुताबिक खींचें और छोड़ें पर जाएं.

डायरेक्ट्री का क्या होगा?

माफ़ करें, JavaScript का इस्तेमाल करके, किसी डायरेक्ट्री को ऐक्सेस करने का कोई अच्छा तरीका नहीं है.

<input type="file"> एलिमेंट पर मौजूद webkitdirectory एट्रिब्यूट की मदद से, उपयोगकर्ता कोई डायरेक्ट्री या डायरेक्ट्री चुन सकता है. यह सुविधा Firefox और iOS पर Safari को छोड़कर, ज़्यादातर ब्राउज़र पर काम करती है.

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

फ़ाइल का मेटाडेटा पढ़ें

File ऑब्जेक्ट में, फ़ाइल का मेटाडेटा मौजूद होता है. ज़्यादातर ब्राउज़र, फ़ाइल का नाम, फ़ाइल का साइज़, और MIME टाइप की जानकारी देते हैं. हालांकि, प्लैटफ़ॉर्म के हिसाब से, अलग-अलग ब्राउज़र अलग-अलग या ज़्यादा जानकारी दे सकते हैं.

function getMetadataForFileList(fileList) {
  for (const file of fileList) {
    // Not supported in Safari for iOS.
    const name = file.name ? file.name : 'NOT SUPPORTED';
    // Not supported in Firefox for Android or Opera for Android.
    const type = file.type ? file.type : 'NOT SUPPORTED';
    // Unknown cross-browser support.
    const size = file.size ? file.size : 'NOT SUPPORTED';
    console.log({file, name, type, size});
  }
}

इसे input-type-file डेमो में देखा जा सकता है.

किसी फ़ाइल का कॉन्टेंट पढ़ना

मेमोरी में File ऑब्जेक्ट का कॉन्टेंट पढ़ने के लिए, FileReader का इस्तेमाल करें. आपके पास FileReader से, फ़ाइल को अरे बफ़र, डेटा यूआरएल या टेक्स्ट के तौर पर पढ़ने के लिए कहने का विकल्प है:

function readImage(file) {
  // Check if the file is an image.
  if (file.type && !file.type.startsWith('image/')) {
    console.log('File is not an image.', file.type, file);
    return;
  }

  const reader = new FileReader();
  reader.addEventListener('load', (event) => {
    img.src = event.target.result;
  });
  reader.readAsDataURL(file);
}

यह उदाहरण, उपयोगकर्ता से मिले File को पढ़ता है. इसके बाद, उसे डेटा के यूआरएल में बदल देता है. साथ ही, उस डेटा यूआरएल का इस्तेमाल, इमेज को img एलिमेंट में दिखाने के लिए करता है. उपयोगकर्ता ने इमेज फ़ाइल चुनी है या नहीं, इसकी पुष्टि करने का तरीका जानने के लिए, read-image-file डेमो देखें.

किसी फ़ाइल के पढ़े जाने की प्रोग्रेस पर नज़र रखना

बड़ी फ़ाइलों को पढ़ते समय, उपयोगकर्ता को यह बताने में मदद मिल सकती है कि पढ़ने की प्रोग्रेस को कहां तक बढ़ाया गया है. इसके लिए, FileReader से मिले progress इवेंट का इस्तेमाल करें. progress इवेंट में दो प्रॉपर्टी होती हैं: loaded (पढ़ी गई रकम) और total (पढ़ी जाने वाली रकम).

function readFile(file) {
  const reader = new FileReader();
  reader.addEventListener('load', (event) => {
    const result = event.target.result;
    // Do something with result
  });

  reader.addEventListener('progress', (event) => {
    if (event.loaded && event.total) {
      const percent = (event.loaded / event.total) * 100;
      console.log(`Progress: ${Math.round(percent)}`);
    }
  });
  reader.readAsDataURL(file);
}

Unsplash से विंसेंट बोटा की हीरो इमेज