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

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

File System Access API का नया वर्शन

File System Access API की मदद से, उपयोगकर्ता के लोकल सिस्टम पर मौजूद फ़ाइलों और डायरेक्ट्री को पढ़ा और उनमें बदलाव किया जा सकता है. यह Chrome और Edge जैसे Chromium पर आधारित ज़्यादातर ब्राउज़र में उपलब्ध है. इसके बारे में ज़्यादा जानने के लिए, The 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 for Android और 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 से विंसेंट बोटा की हीरो इमेज