ফাইল সিস্টেম অ্যাক্সেস API: স্থানীয় ফাইলগুলিতে অ্যাক্সেস সহজ করা

ফাইল সিস্টেম অ্যাক্সেস API ওয়েব অ্যাপগুলিকে ব্যবহারকারীর ডিভাইসে ফাইল এবং ফোল্ডারগুলিতে সরাসরি পরিবর্তনগুলি পড়তে বা সংরক্ষণ করতে দেয়৷

ফাইল সিস্টেম অ্যাক্সেস API কি?

ফাইল সিস্টেম অ্যাক্সেস API বিকাশকারীদের শক্তিশালী ওয়েব অ্যাপ তৈরি করতে সক্ষম করে যা ব্যবহারকারীর স্থানীয় ডিভাইসে ফাইলগুলির সাথে ইন্টারঅ্যাক্ট করে, যেমন IDE, ফটো এবং ভিডিও সম্পাদক, পাঠ্য সম্পাদক এবং আরও অনেক কিছু। কোনও ব্যবহারকারী একটি ওয়েব অ্যাপ অ্যাক্সেস দেওয়ার পরে, এই API তাদের ব্যবহারকারীর ডিভাইসে ফাইল এবং ফোল্ডারগুলিতে সরাসরি পরিবর্তনগুলি পড়তে বা সংরক্ষণ করতে দেয়। ফাইল পড়া এবং লেখার বাইরে, ফাইল সিস্টেম অ্যাক্সেস API একটি ডিরেক্টরি খুলতে এবং এর বিষয়বস্তু গণনা করার ক্ষমতা প্রদান করে।

আপনি যদি আগে ফাইল পড়া এবং লেখার সাথে কাজ করে থাকেন তবে আমি যা শেয়ার করতে যাচ্ছি তার বেশিরভাগই আপনার কাছে পরিচিত হবে। আমি আপনাকে যাইহোক এটি পড়তে উত্সাহিত করি, কারণ সমস্ত সিস্টেম একরকম নয়।

ফাইল সিস্টেম অ্যাক্সেস API Windows, macOS, ChromeOS এবং Linux-এ বেশিরভাগ Chromium ব্রাউজারে সমর্থিত। একটি উল্লেখযোগ্য ব্যতিক্রম হল Brave যেখানে এটি বর্তমানে শুধুমাত্র একটি পতাকার পিছনে উপলব্ধcrbug.com/1011535 এর প্রেক্ষাপটে অ্যান্ড্রয়েডের জন্য সমর্থন কাজ করা হচ্ছে।

ফাইল সিস্টেম অ্যাক্সেস API ব্যবহার করে

ফাইল সিস্টেম অ্যাক্সেস API এর শক্তি এবং উপযোগিতা দেখাতে, আমি একটি একক ফাইল পাঠ্য সম্পাদক লিখেছি। এটি আপনাকে একটি পাঠ্য ফাইল খুলতে, এটি সম্পাদনা করতে, পরিবর্তনগুলিকে ডিস্কে সংরক্ষণ করতে বা একটি নতুন ফাইল শুরু করতে এবং ডিস্কে পরিবর্তনগুলি সংরক্ষণ করতে দেয়। এটি অভিনব কিছু নয়, তবে ধারণাগুলি বুঝতে আপনাকে সাহায্য করার জন্য যথেষ্ট সরবরাহ করে।

ব্রাউজার সমর্থন

ব্রাউজার সমর্থন

  • ক্রোম: 86।
  • প্রান্ত: 86।
  • ফায়ারফক্স: সমর্থিত নয়।
  • সাফারি: সমর্থিত নয়।

উৎস

বৈশিষ্ট্য সনাক্তকরণ

ফাইল সিস্টেম অ্যাক্সেস API সমর্থিত কিনা তা খুঁজে বের করতে, আপনার আগ্রহী পিকার পদ্ধতি বিদ্যমান কিনা তা পরীক্ষা করুন।

if ('showOpenFilePicker' in self) {
  // The `showOpenFilePicker()` method of the File System Access API is supported.
}

চেষ্টা করে দেখুন

টেক্সট এডিটর ডেমোতে ফাইল সিস্টেম অ্যাক্সেস এপিআই দেখুন।

স্থানীয় ফাইল সিস্টেম থেকে একটি ফাইল পড়ুন

প্রথম ব্যবহারের ক্ষেত্রে আমি যেটি মোকাবেলা করতে চাই তা হল ব্যবহারকারীকে একটি ফাইল চয়ন করতে বলা, তারপর ডিস্ক থেকে সেই ফাইলটি খুলুন এবং পড়ুন।

ব্যবহারকারীকে পড়ার জন্য একটি ফাইল বাছাই করতে বলুন

ফাইল সিস্টেম অ্যাক্সেস API-এর প্রবেশ বিন্দু হল window.showOpenFilePicker() । কল করা হলে, এটি একটি ফাইল পিকার ডায়ালগ দেখায় এবং ব্যবহারকারীকে একটি ফাইল নির্বাচন করতে অনুরোধ করে। তারা একটি ফাইল নির্বাচন করার পরে, API ফাইল হ্যান্ডেলগুলির একটি অ্যারে প্রদান করে। একটি ঐচ্ছিক options প্যারামিটার আপনাকে ফাইল পিকারের আচরণকে প্রভাবিত করতে দেয়, উদাহরণস্বরূপ, ব্যবহারকারীকে একাধিক ফাইল বা ডিরেক্টরি বা বিভিন্ন ধরনের ফাইল নির্বাচন করার অনুমতি দিয়ে। নির্দিষ্ট কোনো বিকল্প ছাড়াই, ফাইল পিকার ব্যবহারকারীকে একটি একক ফাইল নির্বাচন করতে দেয়। এটি একটি পাঠ্য সম্পাদকের জন্য উপযুক্ত।

অন্যান্য অনেক শক্তিশালী API-এর মতো, showOpenFilePicker() কল করা অবশ্যই একটি সুরক্ষিত প্রেক্ষাপটে করা উচিত এবং ব্যবহারকারীর অঙ্গভঙ্গির মধ্যে থেকে কল করা আবশ্যক৷

let fileHandle;
butOpenFile.addEventListener('click', async () => {
  // Destructure the one-element array.
  [fileHandle] = await window.showOpenFilePicker();
  // Do something with the file handle.
});

একবার ব্যবহারকারী একটি ফাইল নির্বাচন করলে, showOpenFilePicker() হ্যান্ডেলগুলির একটি অ্যারে প্রদান করে, এই ক্ষেত্রে একটি FileSystemFileHandle সহ একটি এক-এলিমেন্ট অ্যারে যা ফাইলের সাথে ইন্টারঅ্যাক্ট করার জন্য প্রয়োজনীয় বৈশিষ্ট্য এবং পদ্ধতি ধারণ করে।

ফাইল হ্যান্ডেলের একটি রেফারেন্স রাখা সহায়ক যাতে এটি পরে ব্যবহার করা যায়। ফাইলের পরিবর্তনগুলি সংরক্ষণ করতে বা অন্য কোনও ফাইল অপারেশন করতে এটির প্রয়োজন হবে৷

ফাইল সিস্টেম থেকে একটি ফাইল পড়ুন

এখন আপনার কাছে একটি ফাইলের একটি হ্যান্ডেল আছে, আপনি ফাইলের বৈশিষ্ট্যগুলি পেতে পারেন, বা ফাইলটি নিজেই অ্যাক্সেস করতে পারেন। আপাতত, আমি এর বিষয়বস্তু পড়ব। handle.getFile() কল করা একটি File অবজেক্ট ফেরত দেয়, যাতে একটি ব্লব থাকে। ব্লব থেকে ডেটা পেতে, এর একটি পদ্ধতিতে কল করুন, ( slice() , stream() , text() , অথবা arrayBuffer() )।

const file = await fileHandle.getFile();
const contents = await file.text();

FileSystemFileHandle.getFile() দ্বারা প্রত্যাবর্তিত File অবজেক্ট শুধুমাত্র ততক্ষণ পঠনযোগ্য হয় যতক্ষণ না ডিস্কের অন্তর্নিহিত ফাইলটি পরিবর্তিত না হয়। ডিস্কের ফাইলটি পরিবর্তন করা হলে, File অবজেক্টটি অপঠনযোগ্য হয়ে যায় এবং পরিবর্তিত ডেটা পড়ার জন্য একটি নতুন File অবজেক্ট পেতে আপনাকে আবার getFile() কল করতে হবে।

এটা সব একসাথে নির্বাণ

ব্যবহারকারীরা ওপেন বোতামে ক্লিক করলে, ব্রাউজার একটি ফাইল পিকার দেখায়। একবার তারা একটি ফাইল নির্বাচন করলে, অ্যাপটি বিষয়বস্তু পড়ে এবং একটি <textarea> এ রাখে।

let fileHandle;
butOpenFile.addEventListener('click', async () => {
  [fileHandle] = await window.showOpenFilePicker();
  const file = await fileHandle.getFile();
  const contents = await file.text();
  textArea.value = contents;
});

স্থানীয় ফাইল সিস্টেমে ফাইলটি লিখুন

পাঠ্য সম্পাদকে, একটি ফাইল সংরক্ষণ করার দুটি উপায় রয়েছে: সংরক্ষণ করুন এবং সংরক্ষণ করুনসংরক্ষণ পূর্বে পুনরুদ্ধার করা ফাইল হ্যান্ডেল ব্যবহার করে পরিবর্তনগুলিকে মূল ফাইলে ফিরিয়ে দেয়। কিন্তু Save As একটি নতুন ফাইল তৈরি করে, এবং এইভাবে একটি নতুন ফাইল হ্যান্ডেল প্রয়োজন।

একটি নতুন ফাইল তৈরি করুন

একটি ফাইল সংরক্ষণ করতে, showSaveFilePicker() কল করুন, যা ফাইল পিকারকে "সংরক্ষণ" মোডে দেখায়, ব্যবহারকারীকে একটি নতুন ফাইল বাছাই করার অনুমতি দেয় যা তারা সংরক্ষণের জন্য ব্যবহার করতে চায়৷ পাঠ্য সম্পাদকের জন্য, আমি এটি স্বয়ংক্রিয়ভাবে একটি .txt এক্সটেনশন যোগ করতে চেয়েছিলাম, তাই আমি কিছু অতিরিক্ত পরামিতি প্রদান করেছি।

async function getNewFileHandle() {
  const options = {
    types: [
      {
        description: 'Text Files',
        accept: {
          'text/plain': ['.txt'],
        },
      },
    ],
  };
  const handle = await window.showSaveFilePicker(options);
  return handle;
}

ডিস্কে পরিবর্তনগুলি সংরক্ষণ করুন

আপনি GitHub- এ আমার টেক্সট এডিটর ডেমোতে একটি ফাইলের পরিবর্তনগুলি সংরক্ষণ করার জন্য সমস্ত কোড খুঁজে পেতে পারেন। মূল ফাইল সিস্টেম ইন্টারঅ্যাকশন fs-helpers.js এ রয়েছে। তার সবচেয়ে সহজ, প্রক্রিয়া নিম্নলিখিত কোড মত দেখায়. আমি প্রতিটি পদক্ষেপের মধ্য দিয়ে হাঁটব এবং এটি ব্যাখ্যা করব।

// fileHandle is an instance of FileSystemFileHandle..
async function writeFile(fileHandle, contents) {
  // Create a FileSystemWritableFileStream to write to.
  const writable = await fileHandle.createWritable();
  // Write the contents of the file to the stream.
  await writable.write(contents);
  // Close the file and write the contents to disk.
  await writable.close();
}

ডিস্কে ডেটা লেখার জন্য একটি FileSystemWritableFileStream অবজেক্ট, WritableStream এর একটি সাবক্লাস ব্যবহার করা হয়। ফাইল হ্যান্ডেল অবজেক্টে createWritable() কল করে স্ট্রীম তৈরি করুন। যখন createWritable() কল করা হয়, ব্রাউজার প্রথমে পরীক্ষা করে যে ব্যবহারকারী ফাইলটিতে লেখার অনুমতি দিয়েছে কিনা। যদি লেখার অনুমতি না দেওয়া হয়, ব্রাউজার ব্যবহারকারীকে অনুমতির জন্য অনুরোধ করে। যদি অনুমতি না দেওয়া হয়, createWritable() একটি DOMException নিক্ষেপ করে, এবং অ্যাপটি ফাইলটিতে লিখতে সক্ষম হবে না। পাঠ্য সম্পাদকে, DOMException অবজেক্টগুলি saveFile() পদ্ধতিতে পরিচালনা করা হয়।

write() পদ্ধতিটি একটি স্ট্রিং নেয়, যা একটি পাঠ্য সম্পাদকের জন্য প্রয়োজনীয়। তবে এটি একটি বাফারসোর্স বা একটি ব্লবও নিতে পারে। উদাহরণস্বরূপ, আপনি সরাসরি এটিতে একটি স্ট্রিম পাইপ করতে পারেন:

async function writeURLToFile(fileHandle, url) {
  // Create a FileSystemWritableFileStream to write to.
  const writable = await fileHandle.createWritable();
  // Make an HTTP request for the contents.
  const response = await fetch(url);
  // Stream the response into the file.
  await response.body.pipeTo(writable);
  // pipeTo() closes the destination pipe by default, no need to close it.
}

আপনি একটি নির্দিষ্ট অবস্থানে ফাইলটি আপডেট করতে বা ফাইলটির আকার পরিবর্তন করতে স্ট্রীমের মধ্যে seek() , বা truncate()

একটি প্রস্তাবিত ফাইলের নাম এবং স্টার্ট ডিরেক্টরি উল্লেখ করা হচ্ছে

অনেক ক্ষেত্রে আপনি আপনার অ্যাপকে একটি ডিফল্ট ফাইলের নাম বা অবস্থানের পরামর্শ দিতে চাইতে পারেন। উদাহরণস্বরূপ, একজন পাঠ্য সম্পাদক Untitled পরিবর্তে Untitled Text.txt এর একটি ডিফল্ট ফাইলের নাম প্রস্তাব করতে চাইতে পারেন। showSaveFilePicker বিকল্পগুলির অংশ হিসাবে আপনি একটি suggestedName সম্পত্তি পাস করে এটি অর্জন করতে পারেন।

const fileHandle = await self.showSaveFilePicker({
  suggestedName: 'Untitled Text.txt',
  types: [{
    description: 'Text documents',
    accept: {
      'text/plain': ['.txt'],
    },
  }],
});

একই ডিফল্ট স্টার্ট ডিরেক্টরির জন্য যায়। আপনি যদি একটি পাঠ্য সম্পাদক তৈরি করছেন, আপনি ডিফল্ট documents ফোল্ডারে ফাইল সংরক্ষণ বা ফাইল খোলা ডায়ালগ শুরু করতে চাইতে পারেন, যেখানে একটি চিত্র সম্পাদকের জন্য, ডিফল্ট pictures ফোল্ডারে শুরু করতে চাইতে পারেন। আপনি showSaveFilePicker , showDirectoryPicker() বা showOpenFilePicker পদ্ধতিতে startIn প্রপার্টি পাস করে একটি ডিফল্ট স্টার্ট ডিরেক্টরির পরামর্শ দিতে পারেন।

const fileHandle = await self.showOpenFilePicker({
  startIn: 'pictures'
});

সুপরিচিত সিস্টেম ডিরেক্টরির তালিকা হল:

  • desktop : ব্যবহারকারীর ডেস্কটপ ডিরেক্টরি, যদি এমন কিছু থাকে।
  • documents : ডাইরেক্টরি যেখানে ব্যবহারকারীর দ্বারা তৈরি ডকুমেন্টগুলি সাধারণত সংরক্ষণ করা হবে।
  • downloads : ডাইরেক্টরি যেখানে ডাউনলোড করা ফাইল সাধারণত সংরক্ষণ করা হবে।
  • music : ডিরেক্টরি যেখানে অডিও ফাইল সাধারণত সংরক্ষণ করা হবে।
  • pictures : ডিরেক্টরি যেখানে ফটো এবং অন্যান্য স্থির ছবি সাধারণত সংরক্ষণ করা হবে।
  • videos : ডিরেক্টরি যেখানে ভিডিও বা চলচ্চিত্র সাধারণত সংরক্ষণ করা হবে।

সুপরিচিত সিস্টেম ডিরেক্টরি ছাড়াও, আপনি startIn এর মান হিসাবে একটি বিদ্যমান ফাইল বা ডিরেক্টরি হ্যান্ডেল পাস করতে পারেন। ডায়ালগটি তখন একই ডিরেক্টরিতে খুলবে।

// Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
  startIn: directoryHandle
});

বিভিন্ন ফাইল পিকারের উদ্দেশ্য উল্লেখ করা

কখনও কখনও অ্যাপ্লিকেশন বিভিন্ন উদ্দেশ্যে বিভিন্ন পিকার আছে. উদাহরণস্বরূপ, একটি সমৃদ্ধ পাঠ্য সম্পাদক ব্যবহারকারীকে পাঠ্য ফাইলগুলি খোলার অনুমতি দিতে পারে, তবে ছবি আমদানি করতেও পারে। ডিফল্টরূপে, প্রতিটি ফাইল পিকার শেষ-স্মরণীয় স্থানে খুলবে। আপনি প্রতিটি ধরনের পিকারের জন্য id মান সংরক্ষণ করে এটিকে এড়াতে পারেন। যদি একটি id নির্দিষ্ট করা হয়, ফাইল পিকার বাস্তবায়ন সেই id জন্য একটি পৃথক সর্বশেষ-ব্যবহৃত ডিরেক্টরি মনে রাখে।

const fileHandle1 = await self.showSaveFilePicker({
  id: 'openText',
});

const fileHandle2 = await self.showSaveFilePicker({
  id: 'importImage',
});

IndexedDB-তে ফাইল হ্যান্ডেল বা ডিরেক্টরি হ্যান্ডলগুলি সংরক্ষণ করা

ফাইল হ্যান্ডলগুলি এবং ডিরেক্টরি হ্যান্ডেলগুলি ক্রমানুসারে করা যায়, যার অর্থ হল আপনি একটি ফাইল বা ডিরেক্টরি হ্যান্ডেল IndexedDB-তে সংরক্ষণ করতে পারেন, অথবা একই শীর্ষ-স্তরের উত্সের মধ্যে পাঠাতে postMessage() কল করতে পারেন৷

IndexedDB-তে ফাইল বা ডিরেক্টরি হ্যান্ডেলগুলি সংরক্ষণ করার অর্থ হল আপনি স্টেট সংরক্ষণ করতে পারেন, বা মনে রাখতে পারেন যে ব্যবহারকারী কোন ফাইল বা ডিরেক্টরিতে কাজ করছেন। এটি সম্প্রতি খোলা বা সম্পাদিত ফাইলগুলির একটি তালিকা রাখা, অ্যাপটি খোলার পরে শেষ ফাইলটি পুনরায় খোলার প্রস্তাব, পূর্ববর্তী কার্যকারী ডিরেক্টরি পুনরুদ্ধার করা এবং আরও অনেক কিছু করা সম্ভব করে তোলে। টেক্সট এডিটরে, আমি ব্যবহারকারীর খোলা পাঁচটি সাম্প্রতিক ফাইলের একটি তালিকা সঞ্চয় করি, যাতে সেই ফাইলগুলি আবার অ্যাক্সেস করা সম্ভব হয়।

নিম্নলিখিত কোড উদাহরণটি একটি ফাইল হ্যান্ডেল এবং একটি ডিরেক্টরি হ্যান্ডেল সংরক্ষণ এবং পুনরুদ্ধার দেখায়। আপনি গ্লিচের উপর কাজ করে এটি দেখতে পারেন। (আমি সংক্ষিপ্ততার জন্য idb-keyval লাইব্রেরি ব্যবহার করি।)

import { get, set } from 'https://unpkg.com/idb-keyval@5.0.2/dist/esm/index.js';

const pre1 = document.querySelector('pre.file');
const pre2 = document.querySelector('pre.directory');
const button1 = document.querySelector('button.file');
const button2 = document.querySelector('button.directory');

// File handle
button1.addEventListener('click', async () => {
  try {
    const fileHandleOrUndefined = await get('file');
    if (fileHandleOrUndefined) {
      pre1.textContent = `Retrieved file handle "${fileHandleOrUndefined.name}" from IndexedDB.`;
      return;
    }
    const [fileHandle] = await window.showOpenFilePicker();
    await set('file', fileHandle);
    pre1.textContent = `Stored file handle for "${fileHandle.name}" in IndexedDB.`;
  } catch (error) {
    alert(error.name, error.message);
  }
});

// Directory handle
button2.addEventListener('click', async () => {
  try {
    const directoryHandleOrUndefined = await get('directory');
    if (directoryHandleOrUndefined) {
      pre2.textContent = `Retrieved directroy handle "${directoryHandleOrUndefined.name}" from IndexedDB.`;
      return;
    }
    const directoryHandle = await window.showDirectoryPicker();
    await set('directory', directoryHandle);
    pre2.textContent = `Stored directory handle for "${directoryHandle.name}" in IndexedDB.`;
  } catch (error) {
    alert(error.name, error.message);
  }
});

সংরক্ষিত ফাইল বা ডিরেক্টরি হ্যান্ডেল এবং অনুমতি

যেহেতু অনুমতিগুলি সবসময় সেশনগুলির মধ্যে থাকে না , তাই আপনাকে যাচাই করা উচিত যে ব্যবহারকারী queryPermission() ব্যবহার করে ফাইল বা ডিরেক্টরিতে অনুমতি দিয়েছে কিনা। যদি তারা না করে থাকে, তাহলে (পুনরায়) অনুরোধ করতে requestPermission() কে কল করুন। এটি ফাইল এবং ডিরেক্টরি হ্যান্ডলগুলির জন্য একই কাজ করে। আপনাকে যথাক্রমে fileOrDirectoryHandle.requestPermission(descriptor) বা fileOrDirectoryHandle.queryPermission(descriptor) চালাতে হবে।

টেক্সট এডিটরে, আমি একটি verifyPermission() পদ্ধতি তৈরি করেছি যা ব্যবহারকারী ইতিমধ্যে অনুমতি দিয়েছে কিনা তা পরীক্ষা করে এবং প্রয়োজন হলে অনুরোধ করে।

async function verifyPermission(fileHandle, readWrite) {
  const options = {};
  if (readWrite) {
    options.mode = 'readwrite';
  }
  // Check if permission was already granted. If so, return true.
  if ((await fileHandle.queryPermission(options)) === 'granted') {
    return true;
  }
  // Request permission. If the user grants permission, return true.
  if ((await fileHandle.requestPermission(options)) === 'granted') {
    return true;
  }
  // The user didn't grant permission, so return false.
  return false;
}

পড়ার অনুরোধের সাথে লেখার অনুমতির অনুরোধ করে, আমি অনুমতি প্রম্পটের সংখ্যা হ্রাস করেছি; ব্যবহারকারী ফাইলটি খোলার সময় একটি প্রম্পট দেখে এবং এটি পড়তে এবং লিখতে উভয়ের অনুমতি দেয়।

একটি ডিরেক্টরি খোলা এবং এর বিষয়বস্তু গণনা করা

একটি ডিরেক্টরিতে সমস্ত ফাইল গণনা করতে, showDirectoryPicker() কল করুন। ব্যবহারকারী একটি পিকারে একটি ডিরেক্টরি নির্বাচন করে, তারপরে একটি FileSystemDirectoryHandle ফেরত দেওয়া হয়, যা আপনাকে ডিরেক্টরির ফাইলগুলি গণনা করতে এবং অ্যাক্সেস করতে দেয়। ডিফল্টরূপে, আপনার ডিরেক্টরির ফাইলগুলিতে পড়ার অ্যাক্সেস থাকবে, তবে আপনার যদি লেখার অ্যাক্সেসের প্রয়োজন হয়, আপনি পদ্ধতিতে { mode: 'readwrite' } পাস করতে পারেন।

butDir.addEventListener('click', async () => {
  const dirHandle = await window.showDirectoryPicker();
  for await (const entry of dirHandle.values()) {
    console.log(entry.kind, entry.name);
  }
});

আপনি যদি অতিরিক্তভাবে getFile() ব্যবহার করে প্রতিটি ফাইল অ্যাক্সেস করতে চান, উদাহরণস্বরূপ, পৃথক ফাইলের আকারগুলি পেতে, প্রতিটি ফলাফলের জন্য ক্রমানুসারে await ব্যবহার করবেন না, বরং সমান্তরালভাবে সমস্ত ফাইল প্রক্রিয়া করুন, উদাহরণস্বরূপ, Promise.all() ব্যবহার করে .

butDir.addEventListener('click', async () => {
  const dirHandle = await window.showDirectoryPicker();
  const promises = [];
  for await (const entry of dirHandle.values()) {
    if (entry.kind !== 'file') {
      continue;
    }
    promises.push(entry.getFile().then((file) => `${file.name} (${file.size})`));
  }
  console.log(await Promise.all(promises));
});

একটি ডিরেক্টরিতে ফাইল এবং ফোল্ডার তৈরি বা অ্যাক্সেস করা

একটি ডিরেক্টরি থেকে, আপনি getFileHandle() বা যথাক্রমে getDirectoryHandle() পদ্ধতি ব্যবহার করে ফাইল এবং ফোল্ডারগুলি তৈরি বা অ্যাক্সেস করতে পারেন। একটি ঐচ্ছিক options অবজেক্টে create এর একটি কী এবং true বা false এর বুলিয়ান মান দিয়ে, আপনি নির্ধারণ করতে পারেন যে একটি নতুন ফাইল বা ফোল্ডার তৈরি করা উচিত যদি এটি বিদ্যমান না থাকে।

// In an existing directory, create a new directory named "My Documents".
const newDirectoryHandle = await existingDirectoryHandle.getDirectoryHandle('My Documents', {
  create: true,
});
// In this new directory, create a file named "My Notes.txt".
const newFileHandle = await newDirectoryHandle.getFileHandle('My Notes.txt', { create: true });

একটি ডিরেক্টরিতে একটি আইটেমের পথ সমাধান করা

একটি ডিরেক্টরিতে ফাইল বা ফোল্ডারগুলির সাথে কাজ করার সময়, এটি প্রশ্নে থাকা আইটেমের পথটি সমাধান করতে কার্যকর হতে পারে। এটি যথাযথভাবে নামের resolve() পদ্ধতির সাথে করা যেতে পারে। সমাধানের জন্য, আইটেমটি ডিরেক্টরির প্রত্যক্ষ বা পরোক্ষ সন্তান হতে পারে।

// Resolve the path of the previously created file called "My Notes.txt".
const path = await newDirectoryHandle.resolve(newFileHandle);
// `path` is now ["My Documents", "My Notes.txt"]

একটি ডিরেক্টরিতে ফাইল এবং ফোল্ডার মুছে ফেলা হচ্ছে

আপনি যদি একটি ডিরেক্টরিতে অ্যাক্সেস পেয়ে থাকেন, তাহলে আপনি removeEntry() পদ্ধতির মাধ্যমে অন্তর্ভুক্ত ফাইল এবং ফোল্ডারগুলি মুছে ফেলতে পারেন। ফোল্ডারগুলির জন্য, অপসারণ ঐচ্ছিকভাবে পুনরাবৃত্ত হতে পারে এবং এতে থাকা সমস্ত সাবফোল্ডার এবং ফাইলগুলি অন্তর্ভুক্ত করতে পারে।

// Delete a file.
await directoryHandle.removeEntry('Abandoned Projects.txt');
// Recursively delete a folder.
await directoryHandle.removeEntry('Old Stuff', { recursive: true });

একটি ফাইল বা ফোল্ডার সরাসরি মুছে ফেলা

আপনার যদি একটি ফাইল বা ডিরেক্টরি হ্যান্ডেল অ্যাক্সেস থাকে, তাহলে এটি অপসারণ করতে একটি FileSystemFileHandle বা FileSystemDirectoryHandleremove() কল করুন।

// Delete a file.
await fileHandle.remove();
// Delete a directory.
await directoryHandle.remove();

পুনঃনামকরণ এবং ফাইল এবং ফোল্ডার সরানো

FileSystemHandle ইন্টারফেসে move() কল করে ফাইল এবং ফোল্ডারগুলির নাম পরিবর্তন করা যেতে পারে বা একটি নতুন অবস্থানে সরানো যেতে পারে। FileSystemHandle চাইল্ড ইন্টারফেস FileSystemFileHandle এবং FileSystemDirectoryHandle আছে। move() পদ্ধতিতে এক বা দুটি পরামিতি লাগে। প্রথমটি হয় নতুন নামের একটি স্ট্রিং বা গন্তব্য ফোল্ডারে একটি FileSystemDirectoryHandle হতে পারে। পরবর্তী ক্ষেত্রে, ঐচ্ছিক দ্বিতীয় প্যারামিটারটি নতুন নামের একটি স্ট্রিং, তাই সরানো এবং নাম পরিবর্তন এক ধাপে ঘটতে পারে।

// Rename the file.
await file.move('new_name');
// Move the file to a new directory.
await file.move(directory);
// Move the file to a new directory and rename it.
await file.move(directory, 'newer_name');

টেনে আনুন এবং ড্রপ ইন্টিগ্রেশন

এইচটিএমএল ড্র্যাগ এবং ড্রপ ইন্টারফেসগুলি ওয়েব অ্যাপ্লিকেশনগুলিকে একটি ওয়েব পৃষ্ঠায় টেনে আনা এবং ড্রপ করা ফাইলগুলি গ্রহণ করতে সক্ষম করে৷ একটি ড্র্যাগ এবং ড্রপ অপারেশন চলাকালীন, টেনে আনা ফাইল এবং ডিরেক্টরি আইটেমগুলি যথাক্রমে ফাইল এন্ট্রি এবং ডিরেক্টরি এন্ট্রিগুলির সাথে যুক্ত থাকে। DataTransferItem.getAsFileSystemHandle() পদ্ধতি একটি FileSystemFileHandle অবজেক্টের সাথে একটি প্রতিশ্রুতি প্রদান করে যদি টেনে আনা আইটেমটি একটি ফাইল হয়, এবং একটি FileSystemDirectoryHandle অবজেক্টের সাথে একটি প্রতিশ্রুতি যদি টেনে আনা আইটেমটি একটি ডিরেক্টরি হয়। নিম্নলিখিত তালিকা কর্ম এটি দেখায়. উল্লেখ্য যে ড্র্যাগ অ্যান্ড ড্রপ ইন্টারফেসের DataTransferItem.kind ফাইল এবং ডিরেক্টরি উভয়ের জন্যই "file" , যেখানে ফাইল সিস্টেম অ্যাক্সেস API-এর FileSystemHandle.kind হল ফাইলগুলির জন্য "file" এবং ডিরেক্টরিগুলির জন্য "directory"

elem.addEventListener('dragover', (e) => {
  // Prevent navigation.
  e.preventDefault();
});

elem.addEventListener('drop', async (e) => {
  e.preventDefault();

  const fileHandlesPromises = [...e.dataTransfer.items]
    .filter((item) => item.kind === 'file')
    .map((item) => item.getAsFileSystemHandle());

  for await (const handle of fileHandlesPromises) {
    if (handle.kind === 'directory') {
      console.log(`Directory: ${handle.name}`);
    } else {
      console.log(`File: ${handle.name}`);
    }
  }
});

অরিজিন প্রাইভেট ফাইল সিস্টেম অ্যাক্সেস করা

অরিজিন প্রাইভেট ফাইল সিস্টেম হল একটি স্টোরেজ এন্ডপয়েন্ট যেটি নাম থেকে বোঝা যায়, পৃষ্ঠার উৎপত্তির জন্য ব্যক্তিগত। যদিও ব্রাউজারগুলি সাধারণত এই অরিজিন প্রাইভেট ফাইল সিস্টেমের বিষয়বস্তুগুলিকে কোথাও ডিস্কে আটকে রেখে এটি বাস্তবায়ন করে, এটি উদ্দেশ্য নয় যে বিষয়বস্তুগুলি ব্যবহারকারীর অ্যাক্সেসযোগ্য। একইভাবে, প্রাইভেট ফাইল সিস্টেমের বাচ্চাদের নামের সাথে মিল থাকা নামের সাথে ফাইল বা ডিরেক্টরি বিদ্যমান থাকার কোন প্রত্যাশা নেই । যদিও ব্রাউজারটি মনে করতে পারে যে ফাইল আছে, অভ্যন্তরীণভাবে-যেহেতু এটি একটি অরিজিন প্রাইভেট ফাইল সিস্টেম - ব্রাউজার এই "ফাইলগুলি" একটি ডাটাবেস বা অন্য কোনো ডেটা স্ট্রাকচারে সংরক্ষণ করতে পারে। মূলত, আপনি যদি এই API ব্যবহার করেন, তাহলে হার্ড ডিস্কের কোথাও একের সাথে এক মিলে তৈরি ফাইলগুলি খুঁজে পাওয়ার আশা করবেন না । রুট FileSystemDirectoryHandle এ অ্যাক্সেস পেলে আপনি অরিজিন প্রাইভেট ফাইল সিস্টেমে যথারীতি কাজ করতে পারবেন।

const root = await navigator.storage.getDirectory();
// Create a new file handle.
const fileHandle = await root.getFileHandle('Untitled.txt', { create: true });
// Create a new directory handle.
const dirHandle = await root.getDirectoryHandle('New Folder', { create: true });
// Recursively remove a directory.
await root.removeEntry('Old Stuff', { recursive: true });

ব্রাউজার সমর্থন

  • ক্রোম: 86।
  • প্রান্ত: 86।
  • ফায়ারফক্স: 111।
  • সাফারি: 15.2।

উৎস

অরিজিন প্রাইভেট ফাইল সিস্টেম থেকে পারফরম্যান্সের জন্য অপ্টিমাইজ করা ফাইল অ্যাক্সেস করা

অরিজিন প্রাইভেট ফাইল সিস্টেম একটি বিশেষ ধরনের ফাইলে ঐচ্ছিক অ্যাক্সেস প্রদান করে যা পারফরম্যান্সের জন্য অত্যন্ত অপ্টিমাইজ করা হয়, উদাহরণস্বরূপ, একটি ফাইলের বিষয়বস্তুতে ইন-প্লেস এবং এক্সক্লুসিভ লেখার অ্যাক্সেস অফার করে। Chromium 102 এবং পরবর্তীতে, ফাইল অ্যাক্সেস সহজ করার জন্য অরিজিন প্রাইভেট ফাইল সিস্টেমে একটি অতিরিক্ত পদ্ধতি রয়েছে: createSyncAccessHandle() (সিঙ্ক্রোনাস রিড এবং রাইট অপারেশনের জন্য)। এটি FileSystemFileHandle এ উন্মুক্ত করা হয়েছে, কিন্তু একচেটিয়াভাবে ওয়েব ওয়ার্কারদের মধ্যে।

// (Read and write operations are synchronous,
// but obtaining the handle is asynchronous.)
// Synchronous access exclusively in Worker contexts.
const accessHandle = await fileHandle.createSyncAccessHandle();
const writtenBytes = accessHandle.write(buffer);
const readBytes = accessHandle.read(buffer, { at: 1 });

পলিফিলিং

ফাইল সিস্টেম অ্যাক্সেস API পদ্ধতিগুলি সম্পূর্ণরূপে পলিফিল করা সম্ভব নয়।

  • showOpenFilePicker() পদ্ধতিটি একটি <input type="file"> উপাদান দিয়ে আনুমানিক করা যেতে পারে।
  • showSaveFilePicker() পদ্ধতিটি একটি <a download="file_name"> উপাদানের সাথে সিমুলেট করা যেতে পারে, যদিও এটি একটি প্রোগ্রাম্যাটিক ডাউনলোডকে ট্রিগার করে এবং বিদ্যমান ফাইলগুলিকে ওভাররাইট করার অনুমতি দেয় না৷
  • showDirectoryPicker() পদ্ধতিটি অ-মানক <input type="file" webkitdirectory> উপাদানের সাথে কিছুটা অনুকরণ করা যেতে পারে।

আমরা ব্রাউজার-এফএস-অ্যাক্সেস নামে একটি লাইব্রেরি তৈরি করেছি যা যেখানেই সম্ভব ফাইল সিস্টেম অ্যাক্সেস API ব্যবহার করে এবং অন্য সব ক্ষেত্রে এই পরবর্তী সেরা বিকল্পগুলিতে ফিরে আসে।

নিরাপত্তা এবং অনুমতি

Chrome টিম ব্যবহারকারী নিয়ন্ত্রণ এবং স্বচ্ছতা এবং ব্যবহারকারীর এর্গোনমিক্স সহ শক্তিশালী ওয়েব প্ল্যাটফর্ম বৈশিষ্ট্যগুলিতে অ্যাক্সেস নিয়ন্ত্রণে সংজ্ঞায়িত মূল নীতিগুলি ব্যবহার করে ফাইল সিস্টেম অ্যাক্সেস API ডিজাইন এবং প্রয়োগ করেছে৷

একটি ফাইল খোলা বা একটি নতুন ফাইল সংরক্ষণ

পড়ার জন্য ফাইল খুলতে ফাইল পিকার
একটি ফাইল পিকার পড়ার জন্য একটি বিদ্যমান ফাইল খুলতে ব্যবহৃত হয়।

একটি ফাইল খোলার সময়, ব্যবহারকারী ফাইল পিকার ব্যবহার করে একটি ফাইল বা ডিরেক্টরি পড়ার অনুমতি প্রদান করে। খোলা ফাইল পিকার শুধুমাত্র একটি ব্যবহারকারীর অঙ্গভঙ্গি ব্যবহার করে দেখানো যেতে পারে যখন একটি নিরাপদ প্রসঙ্গ থেকে পরিবেশন করা হয়। ব্যবহারকারীরা তাদের মন পরিবর্তন করলে, তারা ফাইল পিকারে নির্বাচন বাতিল করতে পারে এবং সাইটটি কিছুতেই অ্যাক্সেস পায় না। এটি <input type="file"> উপাদানের মতো একই আচরণ।

একটি ফাইল ডিস্কে সংরক্ষণ করতে ফাইল পিকার।
একটি ফাইল পিকার ডিস্কে একটি ফাইল সংরক্ষণ করতে ব্যবহৃত হয়।

একইভাবে, যখন একটি ওয়েব অ্যাপ একটি নতুন ফাইল সংরক্ষণ করতে চায়, ব্রাউজারটি সেভ ফাইল পিকার দেখায়, ব্যবহারকারীকে নতুন ফাইলের নাম এবং অবস্থান নির্দিষ্ট করার অনুমতি দেয়। যেহেতু তারা ডিভাইসে একটি নতুন ফাইল সংরক্ষণ করছে (একটি বিদ্যমান ফাইল ওভাররাইট করার বিপরীতে), ফাইল পিকার অ্যাপটিকে ফাইলটিতে লেখার অনুমতি দেয়।

সীমাবদ্ধ ফোল্ডার

ব্যবহারকারীদের এবং তাদের ডেটা রক্ষা করতে, ব্রাউজার ব্যবহারকারীর নির্দিষ্ট ফোল্ডারে সংরক্ষণ করার ক্ষমতা সীমিত করতে পারে, উদাহরণস্বরূপ, মূল অপারেটিং সিস্টেম ফোল্ডার যেমন Windows, macOS লাইব্রেরি ফোল্ডার। যখন এটি ঘটে, ব্রাউজার একটি প্রম্পট দেখায় এবং ব্যবহারকারীকে একটি ভিন্ন ফোল্ডার বেছে নিতে বলে।

একটি বিদ্যমান ফাইল বা ডিরেক্টরি পরিবর্তন করা

একটি ওয়েব অ্যাপ ব্যবহারকারীর কাছ থেকে সুস্পষ্ট অনুমতি না পেয়ে ডিস্কে একটি ফাইল পরিবর্তন করতে পারে না।

অনুমতি প্রম্পট

যদি একজন ব্যক্তি একটি ফাইলের পরিবর্তনগুলি সংরক্ষণ করতে চান যা তারা পূর্বে পড়ার অ্যাক্সেস মঞ্জুর করেছিল, ব্রাউজারটি একটি অনুমতি প্রম্পট দেখায়, সাইটের জন্য ডিস্কে পরিবর্তনগুলি লেখার অনুমতির অনুরোধ করে৷ অনুমতির অনুরোধ শুধুমাত্র একটি ব্যবহারকারী অঙ্গভঙ্গি দ্বারা ট্রিগার করা যেতে পারে, উদাহরণস্বরূপ, একটি সংরক্ষণ বোতামে ক্লিক করে৷

একটি ফাইল সংরক্ষণ করার আগে দেখানো অনুমতি প্রম্পট।
ব্রাউজারকে বিদ্যমান ফাইলে লেখার অনুমতি দেওয়ার আগে ব্যবহারকারীদের প্রম্পট দেখানো হয়।

বিকল্পভাবে, একটি ওয়েব অ্যাপ যা একাধিক ফাইল সম্পাদনা করে, যেমন একটি IDE, খোলার সময় পরিবর্তনগুলি সংরক্ষণ করার জন্য অনুমতি চাইতে পারে।

ব্যবহারকারী যদি বাতিল নির্বাচন করেন এবং লেখার অ্যাক্সেস না দেন, তাহলে ওয়েব অ্যাপ স্থানীয় ফাইলে পরিবর্তনগুলি সংরক্ষণ করতে পারবে না। এটি ব্যবহারকারীকে তাদের ডেটা সংরক্ষণ করার জন্য একটি বিকল্প পদ্ধতি প্রদান করা উচিত, উদাহরণস্বরূপ ফাইলটিকে "ডাউনলোড" করার উপায় প্রদান করে বা ক্লাউডে ডেটা সংরক্ষণ করা।

স্বচ্ছতা

Omnibox আইকন
ঠিকানা বার আইকন যা নির্দেশ করে যে ব্যবহারকারী ওয়েবসাইটটিকে স্থানীয় ফাইলে সংরক্ষণ করার অনুমতি দিয়েছে।

একবার একজন ব্যবহারকারী স্থানীয় ফাইল সংরক্ষণ করার জন্য একটি ওয়েব অ্যাপকে অনুমতি দিলে, ব্রাউজারটি ঠিকানা বারে একটি আইকন দেখায়। আইকনে ক্লিক করলে ব্যবহারকারীর অ্যাক্সেস দেওয়া ফাইলগুলির তালিকা দেখানো একটি পপ-ওভার খোলে। ব্যবহারকারী যদি পছন্দ করেন তবে সর্বদা সেই অ্যাক্সেস প্রত্যাহার করতে পারেন।

অনুমতি অধ্যবসায়

ওয়েব অ্যাপটি প্রম্পট না করে ফাইলে পরিবর্তনগুলি সংরক্ষণ করা চালিয়ে যেতে পারে যতক্ষণ না এর মূলের জন্য সমস্ত ট্যাব বন্ধ হয়ে যায়। একবার একটি ট্যাব বন্ধ হয়ে গেলে, সাইটটি সমস্ত অ্যাক্সেস হারায়৷ পরের বার ব্যবহারকারী যখন ওয়েব অ্যাপ ব্যবহার করবেন, তখন তাদের ফাইলগুলিতে অ্যাক্সেসের জন্য পুনরায় অনুরোধ করা হবে।

প্রতিক্রিয়া

আমরা ফাইল সিস্টেম অ্যাক্সেস API এর সাথে আপনার অভিজ্ঞতার কথা শুনতে চাই।

API ডিজাইন সম্পর্কে আমাদের বলুন

API সম্পর্কে এমন কিছু আছে যা আপনার প্রত্যাশিত মত কাজ করে না? অথবা আপনার ধারণা বাস্তবায়নের জন্য আপনার প্রয়োজনীয় পদ্ধতি বা বৈশিষ্ট্যগুলি অনুপস্থিত আছে? নিরাপত্তা মডেল সম্পর্কে একটি প্রশ্ন বা মন্তব্য আছে?

বাস্তবায়নে সমস্যা?

আপনি কি Chrome এর বাস্তবায়নের সাথে একটি বাগ খুঁজে পেয়েছেন? অথবা বাস্তবায়ন বৈশিষ্ট থেকে ভিন্ন?

  • https://new.crbug.com এ একটি বাগ ফাইল করুন। আপনি যতটা পারেন বিশদ বিবরণ, পুনরুত্পাদনের জন্য নির্দেশাবলী এবং কম্পোনেন্টগুলিকে Blink>Storage>FileSystem এ সেট করতে ভুলবেন না। দ্রুত রিপ্রো শেয়ার করার জন্য গ্লিচ দুর্দান্ত কাজ করে।

API ব্যবহার করার পরিকল্পনা করছেন?

আপনার সাইটে ফাইল সিস্টেম অ্যাক্সেস API ব্যবহার করার পরিকল্পনা করছেন? আপনার সর্বজনীন সমর্থন আমাদের বৈশিষ্ট্যগুলিকে অগ্রাধিকার দিতে সাহায্য করে এবং অন্যান্য ব্রাউজার বিক্রেতাদের দেখায় যে তাদের সমর্থন করা কতটা গুরুত্বপূর্ণ৷

  • WICG ডিসকোর্স থ্রেডে আপনি কীভাবে এটি ব্যবহার করার পরিকল্পনা করছেন তা শেয়ার করুন।
  • হ্যাশট্যাগ #FileSystemAccess ব্যবহার করে @ChromiumDev- এ একটি টুইট পাঠান এবং আপনি এটি কোথায় এবং কীভাবে ব্যবহার করছেন তা আমাদের জানান।

সহায়ক লিঙ্ক

স্বীকৃতি

ফাইল সিস্টেম অ্যাক্সেস API স্পেকটি মারিজন ক্রুসেলব্রিঙ্ক লিখেছেন।