ব্রাউজারগুলি দীর্ঘ সময়ের জন্য ফাইল এবং ডিরেক্টরিগুলি মোকাবেলা করতে সক্ষম হয়েছে। ফাইল এপিআই ওয়েব অ্যাপ্লিকেশানগুলিতে ফাইল অবজেক্টের প্রতিনিধিত্ব করার পাশাপাশি প্রোগ্রাম্যাটিকভাবে সেগুলি নির্বাচন এবং তাদের ডেটা অ্যাক্সেস করার বৈশিষ্ট্যগুলি সরবরাহ করে। যে মুহুর্তে আপনি কাছাকাছি তাকান, যদিও, যা জ্বলজ্বল করে তা সোনা নয়।
ফাইল মোকাবেলা করার ঐতিহ্যগত উপায়
ফাইল খোলা হচ্ছে
একজন বিকাশকারী হিসাবে, আপনি <input type="file">
উপাদানের মাধ্যমে ফাইলগুলি খুলতে এবং পড়তে পারেন৷ এর সহজতম আকারে, একটি ফাইল খোলার নিচের কোড নমুনার মত কিছু দেখতে পারে। input
অবজেক্ট আপনাকে একটি FileList
দেয়, যা নীচের ক্ষেত্রে শুধুমাত্র একটি File
নিয়ে গঠিত। একটি File
হল একটি নির্দিষ্ট ধরণের Blob
, এবং যে কোনও প্রসঙ্গে ব্যবহার করা যেতে পারে যা একটি ব্লব করতে পারে।
const openFile = async () => {
return new Promise((resolve) => {
const input = document.createElement('input');
input.type = 'file';
input.addEventListener('change', () => {
resolve(input.files[0]);
});
input.click();
});
};
খোলার ডিরেক্টরি
ফোল্ডার (বা ডিরেক্টরি) খোলার জন্য, আপনি <input webkitdirectory>
বৈশিষ্ট্য সেট করতে পারেন। তা ছাড়া, বাকি সবকিছু উপরের মতই কাজ করে। এর বিক্রেতা-প্রিফিক্সড নাম থাকা সত্ত্বেও, webkitdirectory
শুধুমাত্র ক্রোমিয়াম এবং ওয়েবকিট ব্রাউজারেই ব্যবহারযোগ্য নয়, লিগেসি এজএইচটিএমএল-ভিত্তিক এজ এবং ফায়ারফক্সেও ব্যবহারযোগ্য।
সংরক্ষণ করা হচ্ছে (বরং: ডাউনলোড হচ্ছে) ফাইল
একটি ফাইল সংরক্ষণ করার জন্য, ঐতিহ্যগতভাবে, আপনি একটি ফাইল ডাউনলোড করতে সীমাবদ্ধ, যা <a download>
বৈশিষ্ট্যের জন্য ধন্যবাদ কাজ করে। একটি ব্লব দেওয়া হলে, আপনি একটি ব্লব-এ অ্যাঙ্করের href
অ্যাট্রিবিউট সেট করতে পারেন blob:
URL যা আপনি URL.createObjectURL()
পদ্ধতি থেকে পেতে পারেন৷
const saveFile = async (blob) => {
const a = document.createElement('a');
a.download = 'my-file.txt';
a.href = URL.createObjectURL(blob);
a.addEventListener('click', (e) => {
setTimeout(() => URL.revokeObjectURL(a.href), 30 * 1000);
});
a.click();
};
সমস্যা
ডাউনলোড পদ্ধতির একটি বিশাল নেতিবাচক দিক হল একটি ক্লাসিক ওপেন→সম্পাদনা→ সেভ ফ্লো ঘটানোর কোন উপায় নেই, অর্থাৎ মূল ফাইলটি ওভাররাইট করার কোন উপায় নেই। পরিবর্তে, আপনি যখনই "সংরক্ষণ" করবেন তখনই আপনি অপারেটিং সিস্টেমের ডিফল্ট ডাউনলোড ফোল্ডারে মূল ফাইলের একটি নতুন অনুলিপি পাবেন।
ফাইল সিস্টেম অ্যাক্সেস API
ফাইল সিস্টেম অ্যাক্সেস এপিআই অপারেশন, খোলা এবং সংরক্ষণ উভয়ই অনেক সহজ করে তোলে। এটি সত্যিকারের সংরক্ষণ সক্ষম করে, অর্থাৎ, আপনি কেবলমাত্র একটি ফাইল কোথায় সংরক্ষণ করবেন তা চয়ন করতে পারবেন না, তবে একটি বিদ্যমান ফাইল ওভাররাইটও করতে পারবেন।
ফাইল খোলা হচ্ছে
ফাইল সিস্টেম অ্যাক্সেস API এর সাথে, একটি ফাইল খোলা window.showOpenFilePicker()
পদ্ধতিতে একটি কলের ব্যাপার। এই কলটি একটি ফাইল হ্যান্ডেল ফেরত দেয়, যেখান থেকে আপনি getFile()
পদ্ধতির মাধ্যমে প্রকৃত File
পেতে পারেন।
const openFile = async () => {
try {
// Always returns an array.
const [handle] = await window.showOpenFilePicker();
return handle.getFile();
} catch (err) {
console.error(err.name, err.message);
}
};
খোলার ডিরেক্টরি
window.showDirectoryPicker()
কল করে একটি ডিরেক্টরি খুলুন যা ফাইল ডায়ালগ বক্সে ডিরেক্টরি নির্বাচনযোগ্য করে তোলে।
ফাইল সংরক্ষণ করা হচ্ছে
ফাইল সংরক্ষণ করা একইভাবে সহজবোধ্য। একটি ফাইল হ্যান্ডেল থেকে, আপনি createWritable()
মাধ্যমে একটি লেখার যোগ্য স্ট্রীম তৈরি করেন, তারপর আপনি স্ট্রীমের write()
পদ্ধতিতে কল করে ব্লব ডেটা লেখেন এবং অবশেষে আপনি স্ট্রীমটিকে close()
পদ্ধতিতে কল করে বন্ধ করেন।
const saveFile = async (blob) => {
try {
const handle = await window.showSaveFilePicker({
types: [{
accept: {
// Omitted
},
}],
});
const writable = await handle.createWritable();
await writable.write(blob);
await writable.close();
return handle;
} catch (err) {
console.error(err.name, err.message);
}
};
ব্রাউজার-এফএস-অ্যাক্সেস চালু করা হচ্ছে
ফাইল সিস্টেম অ্যাক্সেস API যতটা সূক্ষ্ম, এটি এখনও ব্যাপকভাবে উপলব্ধ নয় ৷
এই কারণেই আমি ফাইল সিস্টেম অ্যাক্সেস API-কে একটি প্রগতিশীল বর্ধন হিসাবে দেখছি। যেমন, ব্রাউজার যখন এটি সমর্থন করে তখন আমি এটি ব্যবহার করতে চাই এবং যদি না হয় তবে ঐতিহ্যগত পদ্ধতি ব্যবহার করতে চাই; সব সময় অসমর্থিত জাভাস্ক্রিপ্ট কোডের অপ্রয়োজনীয় ডাউনলোডের সাথে ব্যবহারকারীকে শাস্তি দেয় না। ব্রাউজার-এফএস-অ্যাক্সেস লাইব্রেরি এই চ্যালেঞ্জের আমার উত্তর।
ডিজাইন দর্শন
যেহেতু ফাইল সিস্টেম অ্যাক্সেস API ভবিষ্যতে পরিবর্তন হওয়ার সম্ভাবনা রয়েছে, ব্রাউজার-fs-অ্যাক্সেস API এর পরে মডেল করা হয় না। অর্থাৎ, লাইব্রেরি একটি পলিফিল নয়, বরং একটি পনিফিল । আপনার অ্যাপটিকে যতটা সম্ভব ছোট রাখার জন্য আপনার যে কার্যকারিতা প্রয়োজন তা আপনি (স্ট্যাটিক বা গতিশীলভাবে) একচেটিয়াভাবে আমদানি করতে পারেন। উপলভ্য পদ্ধতিগুলি হল যথাযথভাবে নামকরণ করা fileOpen()
, directoryOpen()
এবং fileSave()
। অভ্যন্তরীণভাবে, লাইব্রেরি বৈশিষ্ট্য- ফাইল সিস্টেম অ্যাক্সেস API সমর্থিত কিনা তা সনাক্ত করে এবং তারপর সংশ্লিষ্ট কোড পাথ আমদানি করে।
ব্রাউজার-এফএস-অ্যাক্সেস লাইব্রেরি ব্যবহার করে
তিনটি পদ্ধতি ব্যবহার করার জন্য স্বজ্ঞাত। আপনি আপনার অ্যাপের স্বীকৃত mimeTypes
বা ফাইল extensions
নির্দিষ্ট করতে পারেন এবং একাধিক ফাইল বা ডিরেক্টরি নির্বাচনের অনুমতি বা অননুমোদিত করার জন্য একটি multiple
পতাকা সেট করতে পারেন৷ সম্পূর্ণ বিবরণের জন্য, ব্রাউজার-fs-অ্যাক্সেস API ডকুমেন্টেশন দেখুন। নীচের কোড নমুনা দেখায় কিভাবে আপনি ইমেজ ফাইল খুলতে এবং সংরক্ষণ করতে পারেন।
// The imported methods will use the File
// System Access API or a fallback implementation.
import {
fileOpen,
directoryOpen,
fileSave,
} from 'https://unpkg.com/browser-fs-access';
(async () => {
// Open an image file.
const blob = await fileOpen({
mimeTypes: ['image/*'],
});
// Open multiple image files.
const blobs = await fileOpen({
mimeTypes: ['image/*'],
multiple: true,
});
// Open all files in a directory,
// recursively including subdirectories.
const blobsInDirectory = await directoryOpen({
recursive: true
});
// Save a file.
await fileSave(blob, {
fileName: 'Untitled.png',
});
})();
ডেমো
আপনি গ্লিচের একটি ডেমোতে উপরের কোডটি কার্যকর দেখতে পারেন। এর সোর্স কোডও সেখানে পাওয়া যায়। যেহেতু নিরাপত্তার কারণে ক্রস অরিজিন সাব ফ্রেমে ফাইল পিকার দেখানোর অনুমতি নেই, তাই ডেমো এই নিবন্ধে এম্বেড করা যাবে না।
বন্য মধ্যে ব্রাউজার-fs-অ্যাক্সেস লাইব্রেরি
আমার অবসর সময়ে, আমি Excalidraw নামক একটি ইনস্টলযোগ্য PWA- তে সামান্য অবদান রাখি, একটি হোয়াইটবোর্ড টুল যা আপনাকে সহজেই হাতে আঁকা অনুভূতি সহ ডায়াগ্রাম স্কেচ করতে দেয়। এটি সম্পূর্ণরূপে প্রতিক্রিয়াশীল এবং ছোট মোবাইল ফোন থেকে বড় স্ক্রীন সহ কম্পিউটার পর্যন্ত বিভিন্ন ডিভাইসে ভাল কাজ করে৷ এর অর্থ হল ফাইল সিস্টেম অ্যাক্সেস এপিআই সমর্থন করুক বা না করুক তা বিভিন্ন প্ল্যাটফর্মে ফাইলগুলির সাথে মোকাবিলা করতে হবে৷ এটি ব্রাউজার-এফএস-অ্যাক্সেস লাইব্রেরির জন্য এটিকে একটি দুর্দান্ত প্রার্থী করে তোলে।
আমি, উদাহরণস্বরূপ, আমার আইফোনে একটি অঙ্কন শুরু করতে পারি, এটি সংরক্ষণ করতে পারি (প্রযুক্তিগতভাবে: এটি ডাউনলোড করুন, যেহেতু Safari ফাইল সিস্টেম অ্যাক্সেস API সমর্থন করে না) আমার iPhone ডাউনলোড ফোল্ডারে, আমার ডেস্কটপে ফাইলটি খুলতে পারি (এটি আমার থেকে স্থানান্তর করার পরে) phone), ফাইলটি পরিবর্তন করুন, এবং আমার পরিবর্তনের সাথে এটিকে ওভাররাইট করুন, অথবা এমনকি এটি একটি নতুন ফাইল হিসাবে সংরক্ষণ করুন।
বাস্তব জীবনের কোড নমুনা
নীচে, আপনি ব্রাউজার-এফএস-অ্যাক্সেসের একটি বাস্তব উদাহরণ দেখতে পারেন কারণ এটি এক্সক্যালিড্রতে ব্যবহৃত হয়। এই অংশটি /src/data/json.ts
থেকে নেওয়া হয়েছে। বিশেষ আগ্রহের বিষয় হল কিভাবে saveAsJSON()
পদ্ধতিটি হয় একটি ফাইল হ্যান্ডেল পাস করে বা ব্রাউজার-fs-অ্যাক্সেস' fileSave()
পদ্ধতিতে null
, যার ফলে এটিকে একটি হ্যান্ডেল দেওয়া হলে ওভাররাইট করা হয়, বা না হলে একটি নতুন ফাইলে সংরক্ষণ করা হয়।
export const saveAsJSON = async (
elements: readonly ExcalidrawElement[],
appState: AppState,
fileHandle: any,
) => {
const serialized = serializeAsJSON(elements, appState);
const blob = new Blob([serialized], {
type: "application/json",
});
const name = `${appState.name}.excalidraw`;
(window as any).handle = await fileSave(
blob,
{
fileName: name,
description: "Excalidraw file",
extensions: ["excalidraw"],
},
fileHandle || null,
);
};
export const loadFromJSON = async () => {
const blob = await fileOpen({
description: "Excalidraw files",
extensions: ["json", "excalidraw"],
mimeTypes: ["application/json"],
});
return loadFromBlob(blob);
};
UI বিবেচনা
Excalidraw বা আপনার অ্যাপে, UI ব্রাউজারের সমর্থন পরিস্থিতির সাথে খাপ খাইয়ে নেওয়া উচিত। যদি ফাইল সিস্টেম অ্যাক্সেস API সমর্থিত হয় ( if ('showOpenFilePicker' in window) {}
) আপনি একটি সংরক্ষণ বোতাম ছাড়াও একটি সেভ অ্যাজ বোতাম দেখাতে পারেন। নীচের স্ক্রিনশটগুলি আইফোন এবং ক্রোম ডেস্কটপে Excalidraw-এর প্রতিক্রিয়াশীল প্রধান অ্যাপ টুলবারের মধ্যে পার্থক্য দেখায়। আইফোনে কীভাবে সেভ অ্যাজ বোতামটি অনুপস্থিত তা নোট করুন৷
উপসংহার
সিস্টেম ফাইলগুলির সাথে কাজ করা প্রযুক্তিগতভাবে সমস্ত আধুনিক ব্রাউজারে কাজ করে। ফাইল সিস্টেম অ্যাক্সেস API সমর্থন করে এমন ব্রাউজারগুলিতে, আপনি ফাইলগুলিকে সত্য সংরক্ষণ এবং ওভাররাইট করার (শুধু ডাউনলোড নয়) অনুমতি দিয়ে এবং আপনার ব্যবহারকারীদের যেখানে খুশি সেখানে নতুন ফাইল তৈরি করার অনুমতি দিয়ে অভিজ্ঞতাকে আরও ভাল করতে পারেন, যেগুলি ব্রাউজারগুলিতে কার্যকরী থাকে ফাইল সিস্টেম অ্যাক্সেস API সমর্থন করে না। ব্রাউজার-এফএস-অ্যাক্সেস আপনার জীবনকে সহজ করে তোলে প্রগতিশীল বর্ধনের সূক্ষ্মতা মোকাবেলা করে এবং আপনার কোডকে যতটা সম্ভব সহজ করে।
স্বীকৃতি
এই নিবন্ধটি Joe Medley এবং Kayce Basques দ্বারা পর্যালোচনা করা হয়েছে। Excalidraw-এর অবদানকারীদের ধন্যবাদ তাদের প্রকল্পে কাজ করার জন্য এবং আমার পুল অনুরোধ পর্যালোচনা করার জন্য। আনস্প্ল্যাশে ইলিয়া পাভলভের হিরো ছবি ।
,ব্রাউজারগুলি দীর্ঘ সময়ের জন্য ফাইল এবং ডিরেক্টরিগুলি মোকাবেলা করতে সক্ষম হয়েছে। ফাইল এপিআই ওয়েব অ্যাপ্লিকেশানগুলিতে ফাইল অবজেক্টের প্রতিনিধিত্ব করার পাশাপাশি প্রোগ্রাম্যাটিকভাবে সেগুলি নির্বাচন এবং তাদের ডেটা অ্যাক্সেস করার বৈশিষ্ট্যগুলি সরবরাহ করে। যে মুহুর্তে আপনি কাছাকাছি তাকান, যদিও, যা জ্বলজ্বল করে তা সোনা নয়।
ফাইল মোকাবেলা করার ঐতিহ্যগত উপায়
ফাইল খোলা হচ্ছে
একজন বিকাশকারী হিসাবে, আপনি <input type="file">
উপাদানের মাধ্যমে ফাইলগুলি খুলতে এবং পড়তে পারেন৷ এর সহজতম আকারে, একটি ফাইল খোলার নিচের কোড নমুনার মত কিছু দেখতে পারে। input
অবজেক্ট আপনাকে একটি FileList
দেয়, যা নীচের ক্ষেত্রে শুধুমাত্র একটি File
নিয়ে গঠিত। একটি File
হল একটি নির্দিষ্ট ধরণের Blob
, এবং যে কোনও প্রসঙ্গে ব্যবহার করা যেতে পারে যা একটি ব্লব করতে পারে।
const openFile = async () => {
return new Promise((resolve) => {
const input = document.createElement('input');
input.type = 'file';
input.addEventListener('change', () => {
resolve(input.files[0]);
});
input.click();
});
};
খোলার ডিরেক্টরি
ফোল্ডার (বা ডিরেক্টরি) খোলার জন্য, আপনি <input webkitdirectory>
বৈশিষ্ট্য সেট করতে পারেন। তা ছাড়া, বাকি সবকিছু উপরের মতই কাজ করে। এর বিক্রেতা-প্রিফিক্সড নাম থাকা সত্ত্বেও, webkitdirectory
শুধুমাত্র ক্রোমিয়াম এবং ওয়েবকিট ব্রাউজারেই ব্যবহারযোগ্য নয়, লিগেসি এজএইচটিএমএল-ভিত্তিক এজ এবং ফায়ারফক্সেও ব্যবহারযোগ্য।
সংরক্ষণ করা হচ্ছে (বরং: ডাউনলোড হচ্ছে) ফাইল
একটি ফাইল সংরক্ষণ করার জন্য, ঐতিহ্যগতভাবে, আপনি একটি ফাইল ডাউনলোড করতে সীমাবদ্ধ, যা <a download>
বৈশিষ্ট্যের জন্য ধন্যবাদ কাজ করে। একটি ব্লব দেওয়া হলে, আপনি একটি ব্লব-এ অ্যাঙ্করের href
অ্যাট্রিবিউট সেট করতে পারেন blob:
URL যা আপনি URL.createObjectURL()
পদ্ধতি থেকে পেতে পারেন৷
const saveFile = async (blob) => {
const a = document.createElement('a');
a.download = 'my-file.txt';
a.href = URL.createObjectURL(blob);
a.addEventListener('click', (e) => {
setTimeout(() => URL.revokeObjectURL(a.href), 30 * 1000);
});
a.click();
};
সমস্যা
ডাউনলোড পদ্ধতির একটি বিশাল নেতিবাচক দিক হল একটি ক্লাসিক ওপেন→সম্পাদনা→ সেভ ফ্লো ঘটানোর কোন উপায় নেই, অর্থাৎ মূল ফাইলটি ওভাররাইট করার কোন উপায় নেই। পরিবর্তে, আপনি যখনই "সংরক্ষণ" করবেন তখনই আপনি অপারেটিং সিস্টেমের ডিফল্ট ডাউনলোড ফোল্ডারে মূল ফাইলের একটি নতুন অনুলিপি পাবেন।
ফাইল সিস্টেম অ্যাক্সেস API
ফাইল সিস্টেম অ্যাক্সেস এপিআই অপারেশন, খোলা এবং সংরক্ষণ উভয়ই অনেক সহজ করে তোলে। এটি সত্যিকারের সংরক্ষণ সক্ষম করে, অর্থাৎ, আপনি কেবলমাত্র একটি ফাইল কোথায় সংরক্ষণ করবেন তা চয়ন করতে পারবেন না, তবে একটি বিদ্যমান ফাইল ওভাররাইটও করতে পারবেন।
ফাইল খোলা হচ্ছে
ফাইল সিস্টেম অ্যাক্সেস API এর সাথে, একটি ফাইল খোলা window.showOpenFilePicker()
পদ্ধতিতে একটি কলের ব্যাপার। এই কলটি একটি ফাইল হ্যান্ডেল ফেরত দেয়, যেখান থেকে আপনি getFile()
পদ্ধতির মাধ্যমে প্রকৃত File
পেতে পারেন।
const openFile = async () => {
try {
// Always returns an array.
const [handle] = await window.showOpenFilePicker();
return handle.getFile();
} catch (err) {
console.error(err.name, err.message);
}
};
খোলার ডিরেক্টরি
window.showDirectoryPicker()
কল করে একটি ডিরেক্টরি খুলুন যা ফাইল ডায়ালগ বক্সে ডিরেক্টরি নির্বাচনযোগ্য করে তোলে।
ফাইল সংরক্ষণ করা হচ্ছে
ফাইল সংরক্ষণ করা একইভাবে সহজবোধ্য। একটি ফাইল হ্যান্ডেল থেকে, আপনি createWritable()
মাধ্যমে একটি লেখার যোগ্য স্ট্রীম তৈরি করেন, তারপর আপনি স্ট্রীমের write()
পদ্ধতিতে কল করে ব্লব ডেটা লেখেন এবং অবশেষে আপনি স্ট্রীমটিকে close()
পদ্ধতিতে কল করে বন্ধ করেন।
const saveFile = async (blob) => {
try {
const handle = await window.showSaveFilePicker({
types: [{
accept: {
// Omitted
},
}],
});
const writable = await handle.createWritable();
await writable.write(blob);
await writable.close();
return handle;
} catch (err) {
console.error(err.name, err.message);
}
};
ব্রাউজার-এফএস-অ্যাক্সেস চালু করা হচ্ছে
ফাইল সিস্টেম অ্যাক্সেস API যতটা সূক্ষ্ম, এটি এখনও ব্যাপকভাবে উপলব্ধ নয় ৷
এই কারণেই আমি ফাইল সিস্টেম অ্যাক্সেস API-কে একটি প্রগতিশীল বর্ধন হিসাবে দেখছি। যেমন, ব্রাউজার যখন এটি সমর্থন করে তখন আমি এটি ব্যবহার করতে চাই এবং যদি না হয় তবে ঐতিহ্যগত পদ্ধতি ব্যবহার করতে চাই; সব সময় অসমর্থিত জাভাস্ক্রিপ্ট কোডের অপ্রয়োজনীয় ডাউনলোডের সাথে ব্যবহারকারীকে শাস্তি দেয় না। ব্রাউজার-এফএস-অ্যাক্সেস লাইব্রেরি এই চ্যালেঞ্জের আমার উত্তর।
ডিজাইন দর্শন
যেহেতু ফাইল সিস্টেম অ্যাক্সেস API ভবিষ্যতে পরিবর্তন হওয়ার সম্ভাবনা রয়েছে, ব্রাউজার-fs-অ্যাক্সেস API এর পরে মডেল করা হয় না। অর্থাৎ, লাইব্রেরি একটি পলিফিল নয়, বরং একটি পনিফিল । আপনার অ্যাপটিকে যতটা সম্ভব ছোট রাখার জন্য আপনার যে কার্যকারিতা প্রয়োজন তা আপনি (স্ট্যাটিক বা গতিশীলভাবে) একচেটিয়াভাবে আমদানি করতে পারেন। উপলভ্য পদ্ধতিগুলি হল যথাযথভাবে নামকরণ করা fileOpen()
, directoryOpen()
এবং fileSave()
। অভ্যন্তরীণভাবে, লাইব্রেরি বৈশিষ্ট্য- ফাইল সিস্টেম অ্যাক্সেস API সমর্থিত কিনা তা সনাক্ত করে এবং তারপর সংশ্লিষ্ট কোড পাথ আমদানি করে।
ব্রাউজার-এফএস-অ্যাক্সেস লাইব্রেরি ব্যবহার করে
তিনটি পদ্ধতি ব্যবহার করার জন্য স্বজ্ঞাত। আপনি আপনার অ্যাপের স্বীকৃত mimeTypes
বা ফাইল extensions
নির্দিষ্ট করতে পারেন এবং একাধিক ফাইল বা ডিরেক্টরি নির্বাচনের অনুমতি বা অননুমোদিত করার জন্য একটি multiple
পতাকা সেট করতে পারেন৷ সম্পূর্ণ বিবরণের জন্য, ব্রাউজার-fs-অ্যাক্সেস API ডকুমেন্টেশন দেখুন। নীচের কোড নমুনা দেখায় কিভাবে আপনি ইমেজ ফাইল খুলতে এবং সংরক্ষণ করতে পারেন।
// The imported methods will use the File
// System Access API or a fallback implementation.
import {
fileOpen,
directoryOpen,
fileSave,
} from 'https://unpkg.com/browser-fs-access';
(async () => {
// Open an image file.
const blob = await fileOpen({
mimeTypes: ['image/*'],
});
// Open multiple image files.
const blobs = await fileOpen({
mimeTypes: ['image/*'],
multiple: true,
});
// Open all files in a directory,
// recursively including subdirectories.
const blobsInDirectory = await directoryOpen({
recursive: true
});
// Save a file.
await fileSave(blob, {
fileName: 'Untitled.png',
});
})();
ডেমো
আপনি গ্লিচের একটি ডেমোতে উপরের কোডটি কার্যকর দেখতে পারেন। এর সোর্স কোডও সেখানে পাওয়া যায়। যেহেতু নিরাপত্তার কারণে ক্রস অরিজিন সাব ফ্রেমে ফাইল পিকার দেখানোর অনুমতি নেই, তাই ডেমো এই নিবন্ধে এম্বেড করা যাবে না।
বন্য মধ্যে ব্রাউজার-fs-অ্যাক্সেস লাইব্রেরি
আমার অবসর সময়ে, আমি Excalidraw নামক একটি ইনস্টলযোগ্য PWA- তে সামান্য অবদান রাখি, একটি হোয়াইটবোর্ড টুল যা আপনাকে সহজেই হাতে আঁকা অনুভূতি সহ ডায়াগ্রাম স্কেচ করতে দেয়। এটি সম্পূর্ণরূপে প্রতিক্রিয়াশীল এবং ছোট মোবাইল ফোন থেকে বড় স্ক্রীন সহ কম্পিউটার পর্যন্ত বিভিন্ন ডিভাইসে ভাল কাজ করে৷ এর অর্থ হল ফাইল সিস্টেম অ্যাক্সেস এপিআই সমর্থন করুক বা না করুক তা বিভিন্ন প্ল্যাটফর্মে ফাইলগুলির সাথে মোকাবিলা করতে হবে৷ এটি ব্রাউজার-এফএস-অ্যাক্সেস লাইব্রেরির জন্য এটিকে একটি দুর্দান্ত প্রার্থী করে তোলে।
আমি, উদাহরণস্বরূপ, আমার আইফোনে একটি অঙ্কন শুরু করতে পারি, এটি সংরক্ষণ করতে পারি (প্রযুক্তিগতভাবে: এটি ডাউনলোড করুন, যেহেতু Safari ফাইল সিস্টেম অ্যাক্সেস API সমর্থন করে না) আমার iPhone ডাউনলোড ফোল্ডারে, আমার ডেস্কটপে ফাইলটি খুলতে পারি (এটি আমার থেকে স্থানান্তর করার পরে) phone), ফাইলটি পরিবর্তন করুন, এবং আমার পরিবর্তনের সাথে এটিকে ওভাররাইট করুন, অথবা এমনকি এটি একটি নতুন ফাইল হিসাবে সংরক্ষণ করুন।
বাস্তব জীবনের কোড নমুনা
নীচে, আপনি ব্রাউজার-এফএস-অ্যাক্সেসের একটি বাস্তব উদাহরণ দেখতে পারেন কারণ এটি এক্সক্যালিড্রতে ব্যবহৃত হয়। এই অংশটি /src/data/json.ts
থেকে নেওয়া হয়েছে। বিশেষ আগ্রহের বিষয় হল কিভাবে saveAsJSON()
পদ্ধতিটি হয় একটি ফাইল হ্যান্ডেল পাস করে বা ব্রাউজার-fs-অ্যাক্সেস' fileSave()
পদ্ধতিতে null
, যার ফলে এটিকে একটি হ্যান্ডেল দেওয়া হলে ওভাররাইট করা হয়, বা না হলে একটি নতুন ফাইলে সংরক্ষণ করা হয়।
export const saveAsJSON = async (
elements: readonly ExcalidrawElement[],
appState: AppState,
fileHandle: any,
) => {
const serialized = serializeAsJSON(elements, appState);
const blob = new Blob([serialized], {
type: "application/json",
});
const name = `${appState.name}.excalidraw`;
(window as any).handle = await fileSave(
blob,
{
fileName: name,
description: "Excalidraw file",
extensions: ["excalidraw"],
},
fileHandle || null,
);
};
export const loadFromJSON = async () => {
const blob = await fileOpen({
description: "Excalidraw files",
extensions: ["json", "excalidraw"],
mimeTypes: ["application/json"],
});
return loadFromBlob(blob);
};
UI বিবেচনা
Excalidraw বা আপনার অ্যাপে, UI ব্রাউজারের সমর্থন পরিস্থিতির সাথে খাপ খাইয়ে নেওয়া উচিত। যদি ফাইল সিস্টেম অ্যাক্সেস API সমর্থিত হয় ( if ('showOpenFilePicker' in window) {}
) আপনি একটি সংরক্ষণ বোতাম ছাড়াও একটি সেভ অ্যাজ বোতাম দেখাতে পারেন। নীচের স্ক্রিনশটগুলি আইফোন এবং ক্রোম ডেস্কটপে Excalidraw-এর প্রতিক্রিয়াশীল প্রধান অ্যাপ টুলবারের মধ্যে পার্থক্য দেখায়। আইফোনে কীভাবে সেভ অ্যাজ বোতামটি অনুপস্থিত তা নোট করুন৷
উপসংহার
সিস্টেম ফাইলগুলির সাথে কাজ করা প্রযুক্তিগতভাবে সমস্ত আধুনিক ব্রাউজারে কাজ করে। ফাইল সিস্টেম অ্যাক্সেস API সমর্থন করে এমন ব্রাউজারগুলিতে, আপনি ফাইলগুলিকে সত্য সংরক্ষণ এবং ওভাররাইট করার (শুধু ডাউনলোড নয়) অনুমতি দিয়ে এবং আপনার ব্যবহারকারীদের যেখানে খুশি সেখানে নতুন ফাইল তৈরি করার অনুমতি দিয়ে অভিজ্ঞতাকে আরও ভাল করতে পারেন, যেগুলি ব্রাউজারগুলিতে কার্যকরী থাকে ফাইল সিস্টেম অ্যাক্সেস API সমর্থন করে না। ব্রাউজার-এফএস-অ্যাক্সেস আপনার জীবনকে সহজ করে তোলে প্রগতিশীল বর্ধনের সূক্ষ্মতা মোকাবেলা করে এবং আপনার কোডকে যতটা সম্ভব সহজ করে।
স্বীকৃতি
এই নিবন্ধটি Joe Medley এবং Kayce Basques দ্বারা পর্যালোচনা করা হয়েছে। Excalidraw-এর অবদানকারীদের ধন্যবাদ তাদের প্রকল্পে কাজ করার জন্য এবং আমার পুল অনুরোধ পর্যালোচনা করার জন্য। আনস্প্ল্যাশে ইলিয়া পাভলভের হিরো ছবি ।
,ব্রাউজারগুলি দীর্ঘ সময়ের জন্য ফাইল এবং ডিরেক্টরিগুলি মোকাবেলা করতে সক্ষম হয়েছে। ফাইল এপিআই ওয়েব অ্যাপ্লিকেশানগুলিতে ফাইল অবজেক্টের প্রতিনিধিত্ব করার পাশাপাশি প্রোগ্রাম্যাটিকভাবে সেগুলি নির্বাচন এবং তাদের ডেটা অ্যাক্সেস করার বৈশিষ্ট্যগুলি সরবরাহ করে। যে মুহুর্তে আপনি কাছাকাছি তাকান, যদিও, যা জ্বলজ্বল করে তা সোনা নয়।
ফাইল মোকাবেলা করার ঐতিহ্যগত উপায়
ফাইল খোলা হচ্ছে
একজন বিকাশকারী হিসাবে, আপনি <input type="file">
উপাদানের মাধ্যমে ফাইলগুলি খুলতে এবং পড়তে পারেন৷ এর সহজতম আকারে, একটি ফাইল খোলার নিচের কোড নমুনার মত কিছু দেখতে পারে। input
অবজেক্ট আপনাকে একটি FileList
দেয়, যা নীচের ক্ষেত্রে শুধুমাত্র একটি File
নিয়ে গঠিত। একটি File
হল একটি নির্দিষ্ট ধরণের Blob
, এবং যে কোনও প্রসঙ্গে ব্যবহার করা যেতে পারে যা একটি ব্লব করতে পারে।
const openFile = async () => {
return new Promise((resolve) => {
const input = document.createElement('input');
input.type = 'file';
input.addEventListener('change', () => {
resolve(input.files[0]);
});
input.click();
});
};
খোলার ডিরেক্টরি
ফোল্ডার (বা ডিরেক্টরি) খোলার জন্য, আপনি <input webkitdirectory>
বৈশিষ্ট্য সেট করতে পারেন। তা ছাড়া, বাকি সবকিছু উপরের মতই কাজ করে। এর বিক্রেতা-প্রিফিক্সড নাম থাকা সত্ত্বেও, webkitdirectory
শুধুমাত্র ক্রোমিয়াম এবং ওয়েবকিট ব্রাউজারেই ব্যবহারযোগ্য নয়, লিগেসি এজএইচটিএমএল-ভিত্তিক এজ এবং ফায়ারফক্সেও ব্যবহারযোগ্য।
সংরক্ষণ করা হচ্ছে (বরং: ডাউনলোড হচ্ছে) ফাইল
একটি ফাইল সংরক্ষণ করার জন্য, ঐতিহ্যগতভাবে, আপনি একটি ফাইল ডাউনলোড করতে সীমাবদ্ধ, যা <a download>
বৈশিষ্ট্যের জন্য ধন্যবাদ কাজ করে। একটি ব্লব দেওয়া হলে, আপনি একটি ব্লব-এ অ্যাঙ্করের href
অ্যাট্রিবিউট সেট করতে পারেন blob:
URL যা আপনি URL.createObjectURL()
পদ্ধতি থেকে পেতে পারেন৷
const saveFile = async (blob) => {
const a = document.createElement('a');
a.download = 'my-file.txt';
a.href = URL.createObjectURL(blob);
a.addEventListener('click', (e) => {
setTimeout(() => URL.revokeObjectURL(a.href), 30 * 1000);
});
a.click();
};
সমস্যা
ডাউনলোড পদ্ধতির একটি বিশাল নেতিবাচক দিক হল একটি ক্লাসিক ওপেন→সম্পাদনা→ সেভ ফ্লো ঘটানোর কোন উপায় নেই, অর্থাৎ মূল ফাইলটি ওভাররাইট করার কোন উপায় নেই। পরিবর্তে, আপনি যখনই "সংরক্ষণ" করবেন তখনই আপনি অপারেটিং সিস্টেমের ডিফল্ট ডাউনলোড ফোল্ডারে মূল ফাইলের একটি নতুন অনুলিপি পাবেন।
ফাইল সিস্টেম অ্যাক্সেস API
ফাইল সিস্টেম অ্যাক্সেস এপিআই অপারেশন, খোলা এবং সংরক্ষণ উভয়ই অনেক সহজ করে তোলে। এটি সত্যিকারের সংরক্ষণ সক্ষম করে, অর্থাৎ, আপনি কেবলমাত্র একটি ফাইল কোথায় সংরক্ষণ করবেন তা চয়ন করতে পারবেন না, তবে একটি বিদ্যমান ফাইল ওভাররাইটও করতে পারবেন।
ফাইল খোলা হচ্ছে
ফাইল সিস্টেম অ্যাক্সেস API এর সাথে, একটি ফাইল খোলা window.showOpenFilePicker()
পদ্ধতিতে একটি কলের ব্যাপার। এই কলটি একটি ফাইল হ্যান্ডেল ফেরত দেয়, যেখান থেকে আপনি getFile()
পদ্ধতির মাধ্যমে প্রকৃত File
পেতে পারেন।
const openFile = async () => {
try {
// Always returns an array.
const [handle] = await window.showOpenFilePicker();
return handle.getFile();
} catch (err) {
console.error(err.name, err.message);
}
};
খোলার ডিরেক্টরি
window.showDirectoryPicker()
কল করে একটি ডিরেক্টরি খুলুন যা ফাইল ডায়ালগ বক্সে ডিরেক্টরি নির্বাচনযোগ্য করে তোলে।
ফাইল সংরক্ষণ করা হচ্ছে
ফাইল সংরক্ষণ করা একইভাবে সহজবোধ্য। একটি ফাইল হ্যান্ডেল থেকে, আপনি createWritable()
মাধ্যমে একটি লেখার যোগ্য স্ট্রীম তৈরি করেন, তারপর আপনি স্ট্রীমের write()
পদ্ধতিতে কল করে ব্লব ডেটা লেখেন এবং অবশেষে আপনি স্ট্রীমটিকে close()
পদ্ধতিতে কল করে বন্ধ করেন।
const saveFile = async (blob) => {
try {
const handle = await window.showSaveFilePicker({
types: [{
accept: {
// Omitted
},
}],
});
const writable = await handle.createWritable();
await writable.write(blob);
await writable.close();
return handle;
} catch (err) {
console.error(err.name, err.message);
}
};
ব্রাউজার-এফএস-অ্যাক্সেস চালু করা হচ্ছে
ফাইল সিস্টেম অ্যাক্সেস API যতটা সূক্ষ্ম, এটি এখনও ব্যাপকভাবে উপলব্ধ নয় ৷
এই কারণেই আমি ফাইল সিস্টেম অ্যাক্সেস API-কে একটি প্রগতিশীল বর্ধন হিসাবে দেখছি। যেমন, ব্রাউজার যখন এটি সমর্থন করে তখন আমি এটি ব্যবহার করতে চাই এবং যদি না হয় তবে ঐতিহ্যগত পদ্ধতি ব্যবহার করতে চাই; সব সময় অসমর্থিত জাভাস্ক্রিপ্ট কোডের অপ্রয়োজনীয় ডাউনলোডের সাথে ব্যবহারকারীকে শাস্তি দেয় না। ব্রাউজার-এফএস-অ্যাক্সেস লাইব্রেরি এই চ্যালেঞ্জের আমার উত্তর।
ডিজাইন দর্শন
যেহেতু ফাইল সিস্টেম অ্যাক্সেস API ভবিষ্যতে পরিবর্তন হওয়ার সম্ভাবনা রয়েছে, ব্রাউজার-fs-অ্যাক্সেস API এর পরে মডেল করা হয় না। অর্থাৎ, লাইব্রেরি একটি পলিফিল নয়, বরং একটি পনিফিল । আপনার অ্যাপটিকে যতটা সম্ভব ছোট রাখার জন্য আপনার যে কার্যকারিতা প্রয়োজন তা আপনি (স্ট্যাটিক বা গতিশীলভাবে) একচেটিয়াভাবে আমদানি করতে পারেন। উপলভ্য পদ্ধতিগুলি হল যথাযথভাবে নামকরণ করা fileOpen()
, directoryOpen()
এবং fileSave()
। অভ্যন্তরীণভাবে, লাইব্রেরি বৈশিষ্ট্য- ফাইল সিস্টেম অ্যাক্সেস API সমর্থিত কিনা তা সনাক্ত করে এবং তারপর সংশ্লিষ্ট কোড পাথ আমদানি করে।
ব্রাউজার-এফএস-অ্যাক্সেস লাইব্রেরি ব্যবহার করে
তিনটি পদ্ধতি ব্যবহার করার জন্য স্বজ্ঞাত। আপনি আপনার অ্যাপের স্বীকৃত mimeTypes
বা ফাইল extensions
নির্দিষ্ট করতে পারেন এবং একাধিক ফাইল বা ডিরেক্টরি নির্বাচনের অনুমতি বা অননুমোদিত করার জন্য একটি multiple
পতাকা সেট করতে পারেন৷ সম্পূর্ণ বিবরণের জন্য, ব্রাউজার-fs-অ্যাক্সেস API ডকুমেন্টেশন দেখুন। নীচের কোড নমুনা দেখায় কিভাবে আপনি ইমেজ ফাইল খুলতে এবং সংরক্ষণ করতে পারেন।
// The imported methods will use the File
// System Access API or a fallback implementation.
import {
fileOpen,
directoryOpen,
fileSave,
} from 'https://unpkg.com/browser-fs-access';
(async () => {
// Open an image file.
const blob = await fileOpen({
mimeTypes: ['image/*'],
});
// Open multiple image files.
const blobs = await fileOpen({
mimeTypes: ['image/*'],
multiple: true,
});
// Open all files in a directory,
// recursively including subdirectories.
const blobsInDirectory = await directoryOpen({
recursive: true
});
// Save a file.
await fileSave(blob, {
fileName: 'Untitled.png',
});
})();
ডেমো
আপনি গ্লিচের একটি ডেমোতে উপরের কোডটি কার্যকর দেখতে পারেন। এর সোর্স কোডও সেখানে পাওয়া যায়। যেহেতু নিরাপত্তার কারণে ক্রস অরিজিন সাব ফ্রেমে ফাইল পিকার দেখানোর অনুমতি নেই, তাই ডেমো এই নিবন্ধে এম্বেড করা যাবে না।
বন্য মধ্যে ব্রাউজার-fs-অ্যাক্সেস লাইব্রেরি
আমার অবসর সময়ে, আমি Excalidraw নামক একটি ইনস্টলযোগ্য PWA- তে সামান্য অবদান রাখি, একটি হোয়াইটবোর্ড টুল যা আপনাকে সহজেই হাতে আঁকা অনুভূতি সহ ডায়াগ্রাম স্কেচ করতে দেয়। এটি সম্পূর্ণরূপে প্রতিক্রিয়াশীল এবং ছোট মোবাইল ফোন থেকে বড় স্ক্রীন সহ কম্পিউটার পর্যন্ত বিভিন্ন ডিভাইসে ভাল কাজ করে৷ এর অর্থ হল ফাইল সিস্টেম অ্যাক্সেস এপিআই সমর্থন করুক বা না করুক তা বিভিন্ন প্ল্যাটফর্মে ফাইলগুলির সাথে মোকাবিলা করতে হবে৷ এটি ব্রাউজার-এফএস-অ্যাক্সেস লাইব্রেরির জন্য এটিকে একটি দুর্দান্ত প্রার্থী করে তোলে।
আমি, উদাহরণস্বরূপ, আমার আইফোনে একটি অঙ্কন শুরু করতে পারি, এটি সংরক্ষণ করতে পারি (প্রযুক্তিগতভাবে: এটি ডাউনলোড করুন, যেহেতু Safari ফাইল সিস্টেম অ্যাক্সেস API সমর্থন করে না) আমার iPhone ডাউনলোড ফোল্ডারে, আমার ডেস্কটপে ফাইলটি খুলতে পারি (এটি আমার থেকে স্থানান্তর করার পরে) phone), ফাইলটি পরিবর্তন করুন, এবং আমার পরিবর্তনের সাথে এটিকে ওভাররাইট করুন, অথবা এমনকি এটি একটি নতুন ফাইল হিসাবে সংরক্ষণ করুন।
বাস্তব জীবনের কোড নমুনা
নীচে, আপনি ব্রাউজার-এফএস-অ্যাক্সেসের একটি বাস্তব উদাহরণ দেখতে পারেন কারণ এটি এক্সক্যালিড্রতে ব্যবহৃত হয়। এই অংশটি /src/data/json.ts
থেকে নেওয়া হয়েছে। বিশেষ আগ্রহের বিষয় হল কিভাবে saveAsJSON()
পদ্ধতিটি হয় একটি ফাইল হ্যান্ডেল পাস করে বা ব্রাউজার-fs-অ্যাক্সেস' fileSave()
পদ্ধতিতে null
, যার ফলে এটিকে একটি হ্যান্ডেল দেওয়া হলে ওভাররাইট করা হয়, বা না হলে একটি নতুন ফাইলে সংরক্ষণ করা হয়।
export const saveAsJSON = async (
elements: readonly ExcalidrawElement[],
appState: AppState,
fileHandle: any,
) => {
const serialized = serializeAsJSON(elements, appState);
const blob = new Blob([serialized], {
type: "application/json",
});
const name = `${appState.name}.excalidraw`;
(window as any).handle = await fileSave(
blob,
{
fileName: name,
description: "Excalidraw file",
extensions: ["excalidraw"],
},
fileHandle || null,
);
};
export const loadFromJSON = async () => {
const blob = await fileOpen({
description: "Excalidraw files",
extensions: ["json", "excalidraw"],
mimeTypes: ["application/json"],
});
return loadFromBlob(blob);
};
UI বিবেচনা
Excalidraw বা আপনার অ্যাপে, UI ব্রাউজারের সমর্থন পরিস্থিতির সাথে খাপ খাইয়ে নেওয়া উচিত। যদি ফাইল সিস্টেম অ্যাক্সেস API সমর্থিত হয় ( if ('showOpenFilePicker' in window) {}
) আপনি একটি সংরক্ষণ বোতাম ছাড়াও একটি সেভ অ্যাজ বোতাম দেখাতে পারেন। নীচের স্ক্রিনশটগুলি আইফোন এবং ক্রোম ডেস্কটপে Excalidraw-এর প্রতিক্রিয়াশীল প্রধান অ্যাপ টুলবারের মধ্যে পার্থক্য দেখায়। আইফোনে কীভাবে সেভ অ্যাজ বোতামটি অনুপস্থিত তা নোট করুন৷
উপসংহার
সিস্টেম ফাইলগুলির সাথে কাজ করা প্রযুক্তিগতভাবে সমস্ত আধুনিক ব্রাউজারে কাজ করে। ফাইল সিস্টেম অ্যাক্সেস API সমর্থন করে এমন ব্রাউজারগুলিতে, আপনি ফাইলগুলিকে সত্য সংরক্ষণ এবং ওভাররাইট করার (শুধু ডাউনলোড নয়) অনুমতি দিয়ে এবং আপনার ব্যবহারকারীদের যেখানে খুশি সেখানে নতুন ফাইল তৈরি করার অনুমতি দিয়ে অভিজ্ঞতাকে আরও ভাল করতে পারেন, যেগুলি ব্রাউজারগুলিতে কার্যকরী থাকে ফাইল সিস্টেম অ্যাক্সেস API সমর্থন করে না। ব্রাউজার-এফএস-অ্যাক্সেস আপনার জীবনকে সহজ করে তোলে প্রগতিশীল বর্ধনের সূক্ষ্মতা মোকাবেলা করে এবং আপনার কোডকে যতটা সম্ভব সহজ করে।
স্বীকৃতি
এই নিবন্ধটি Joe Medley এবং Kayce Basques দ্বারা পর্যালোচনা করা হয়েছে। Excalidraw-এর অবদানকারীদের ধন্যবাদ তাদের প্রকল্পে কাজ করার জন্য এবং আমার পুল অনুরোধ পর্যালোচনা করার জন্য। আনস্প্ল্যাশে ইলিয়া পাভলভের হিরো ছবি ।