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

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

नया File System Access API

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

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 एट्रिब्यूट की मदद से, उपयोगकर्ता कोई डायरेक्ट्री या डायरेक्ट्री चुन सकता है. यह सुविधा ज़्यादातर मुख्य ब्राउज़र में काम करती है. हालांकि, यह Android के लिए Firefox और iOS पर Safari में काम नहीं करती.

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

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

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

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 से ली गई विंसेंट बोटा की हीरो इमेज