خواندن فایل ها در جاوا اسکریپت

انتخاب و تعامل با فایل ها در دستگاه محلی کاربر یکی از رایج ترین ویژگی های وب است. این به کاربران امکان می دهد فایل ها را انتخاب کرده و آنها را در سرور آپلود کنند، به عنوان مثال، هنگام اشتراک گذاری عکس ها یا ارائه اسناد مالیاتی. همچنین به سایت ها اجازه می دهد بدون نیاز به انتقال داده ها در سراسر شبکه، آنها را بخوانند و دستکاری کنند. در این صفحه نحوه استفاده از جاوا اسکریپت برای تعامل با فایل ها توضیح داده شده است.

API دسترسی به فایل سیستم مدرن

File System Access API راهی برای خواندن و نوشتن از فایل ها و دایرکتوری ها در سیستم محلی کاربر فراهم می کند. این در اکثر مرورگرهای مبتنی بر Chromium مانند Chrome و Edge در دسترس است. برای کسب اطلاعات بیشتر در مورد آن، به The File System Access API مراجعه کنید.

از آنجایی که File System Access API با همه مرورگرها سازگار نیست، توصیه می‌کنیم از مرورگر-fs-access استفاده کنید، یک کتابخانه کمکی که از API جدید در هر کجا که در دسترس است استفاده می‌کند و در صورت نبودن به رویکردهای قدیمی بازمی‌گردد.

کار با فایل ها، به روش کلاسیک

این راهنما به شما نشان می دهد که چگونه با استفاده از روش های جاوا اسکریپت قدیمی با فایل ها تعامل کنید.

فایل ها را انتخاب کنید

دو راه اصلی برای انتخاب فایل‌ها وجود دارد: استفاده از عنصر ورودی HTML و استفاده از یک منطقه کشیدن و رها کردن .

عنصر ورودی HTML

ساده ترین راه برای کاربران برای انتخاب فایل ها استفاده از عنصر <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() رفتار پیش فرض مرورگر را متوقف می کنند و به جای آن اجازه می دهند کد شما اجرا شود. بدون آنها، مرورگر در غیر این صورت از صفحه شما دور می شود و فایل هایی را که کاربر در پنجره مرورگر رها کرده است باز می کند.

برای نمایش زنده، به کشیدن و رها کردن سفارشی مراجعه کنید.

دایرکتوری ها چطور؟

متأسفانه، راه خوبی برای دسترسی به دایرکتوری با استفاده از جاوا اسکریپت وجود ندارد.

ویژگی webkitdirectory در عنصر <input type="file"> به کاربر این امکان را می دهد که یک دایرکتوری یا دایرکتوری ها را انتخاب کند. در اکثر مرورگرهای اصلی به جز فایرفاکس برای اندروید و سافاری در iOS پشتیبانی می شود .

اگر کشیدن و رها کردن فعال باشد، کاربر ممکن است سعی کند یک فهرست را به منطقه رها کردن بکشد. هنگامی که رویداد drop فعال می شود، شامل یک شی 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 مشاهده کنید.

محتوای یک فایل را بخوانید

از FileReader برای خواندن محتوای یک شی File در حافظه استفاده کنید. می توانید به FileReader بگویید که یک فایل را به عنوان بافر آرایه ، URL داده یا متن بخواند:

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 ارائه شده توسط کاربر را می خواند، سپس آن را به URL داده تبدیل می کند و از آن URL داده برای نمایش تصویر در عنصر img استفاده می کند. برای اطلاع از نحوه تأیید اینکه کاربر یک فایل تصویری را انتخاب کرده است، به دمو read-image-file مراجعه کنید.

نظارت بر پیشرفت یک فایل خوانده شده

هنگام خواندن فایل‌های بزرگ، ارائه مقداری UX می‌تواند مفید باشد تا به کاربر بگوید خواندن چقدر پیشرفت کرده است. برای آن، از رویداد progress ارائه شده توسط FileReader استفاده کنید. رویداد 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