آموزش کار با فایلهای ZIP در Node.js
در این مقاله میخوانید
نحوه کار با فایل فشرده در Node.js چطور است؟ چگونه میتوانیم در Node.js با فایلهای زیپشده کار کنیم؟ از مشکلات رایجی که بسیاری از توسعهدهندگان با آن دستوپنجه نرم میکنند، افزایش حجم فایلهای سنگین است که فضای زیادی از هارددیسک را اشغال میکنند. در این شرایط، باید بسیاری از فایلها را به سرور دیگری منتقل کنید یا منابع جدیدی برای سرورتان بخرید. برخی از پلتفرمها بهگونهای طراحی شدهاند که محدودیت اندازه فایل دارند و شما نمیتوانید فایلهایی با حجم زیاد را در آنها ذخیره کنید؛ اما جای نگرانی نیست!
ذخیرهسازی فایلها در فایل ZIP میتواند بدون تغییر حجم فایلها را کاهش دهد. در Node.js، میتوانید از ماژول adm-zip برای ایجاد و خواندن آرشیوهای ZIP استفاده کنید. در این مقاله از وبلاگ پارس پک، نحوه استفاده از ماژول adm-zip برای فشردهسازی و خواندن و خارجکردن فایلها در Node.js را آموزش خواهیم داد؛ پس تا پایان با ما همراه باشید.
پیشنیازها
- Node.js نصبشده روی محیط لوکال یا سرور
- آشنایی با برنامهنویسی Node.js
- آشنایی با Asynchronous Javascript
- آشنایی با نحوه کار با فایلها در Node.js
مراحل کار با فایل فشرده در Node.js
برای استفاده از ZIP Archive در Node.js، باید مراحل زیر را بهترتیب دنبال کنید:
مرحله ۱. ایجاد پروژه (Setting Up the Project)
در این مرحله، دایرکتوری پروژه خود را ایجاد و adm-zip را بهعنوان وابستگی نصب کنید. این دایرکتوری جایی است که فایلهای برنامهتان را نگه میدارید. سپس در بخش بعدی، دایرکتوری دیگری حاوی فایلهای متنی و تصویری ایجاد خواهید کرد.
1. با استفاده از کامند زیر، دایرکتوریای به نام zip_app ایجاد کنید:
mkdir zip_app
2. اکنون برای دسترسی به پوشه جدیدی که ایجاد کردهاید، باید از کامند cd استفاده کنید:
cd zip_app
3. سپس در داخل دایرکتوری، فایل package.json را برای مدیریت وابستگیهای پروژه ایجاد کنید:
npm init -y
4. گزینه y- فایل package.json بهصورت پیشفرض ایجاد میکند. در مرحله بعد، adm-zip را با کامند npm install نصب کنید:
npm install adm-zip
5. با اجرای کامند یادشده، adm-zip نصب و فایل package.json بهروزرسانی میشود. اکنون، دایرکتوریای به نام test ایجاد کنید و به آنجا بروید:
mkdir test && cd test
6. در این دایرکتوری، باید سه فایل متنی را ایجاد و یک فایل تصویری را دانلود کنید. این سه فایل با dummy content پر میشوند تا حجمشان بیشتر شود. این کار به فشردهسازی ZIP در هنگام بایگانی این دایرکتوری کمک میکند.
7. حال file1.txt را ایجاد و با استفاده از کامند زیر آن را با dummy content پر کنید:
yes "dummy content" | head -n 100000 > file1.txt
8. کامند yes استرینگ dummy content را بهطور مکرر ثبت میکند. با استفاده از کامند |، خروجی را از کامند yes ارسال میکنید تا بهعنوان ورودی دستور head استفاده شود. دستور head بخشی از ورودی دادهشده را در خروجی استاندارد چاپ میکند. گزینه n- تعداد خطوطی را مشخص میکند که باید در خروجی استاندارد نوشته شود. درنهایت با استفاده از کامند <، خروجی کامند head را به فایل جدید file file1.txt تغییر میدهید.
برای آموزش گام به گام نوشتن و اجرا کردن اولین برنامه Node.js مقاله زیر را از دست ندهید.
9. اکنون فایل دوم را با استرینگ dummy content ایجاد کنید که 300000 خط تکرار شده است:
yes "dummy content" | head -n 300000 > file2.txt
10. سپس، فایل دیگری با استرینگ dummy content ایجاد کنید که در 600000 خط تکرار شده است:
yes "dummy content" | head -n 600000 > file3.txt
11. درنهایت، یک تصویر را با استفاده از curl در دایرکتوری دانلود کنید:
curl -O https://assets.digitalocean.com/how-to-process-images-in-node-js-with-sharp/underwater.png
12. با دستور زیر، به دایرکتوری اصلی پروژه برگردید:
cd ..
12. استفاده از .. شما را به دایرکتوری منبع که zip_app است، منتقل میکند. حالا دایرکتوری پروژه را راهاندازی و adm-zip را نصب و دایرکتوریای با فایلهایی برای آرشیو ایجاد کردهاید. در مرحله بعدی، دایرکتوریای را با استفاده از ماژول adm-zip آرشیو خواهید کرد.
مرحله ۲. ایجاد ZIP Archive
در این مرحله، از adm-zip برای فشردهسازی و بایگانی دایرکتوریای استفاده میکنید که در قسمت قبل ایجاد کردهاید. بهمنظور آرشیو دایرکتوری، ماژول adm-zip را وارد و از متد ()adLocalFolder برای اضافهکردن دایرکتوری به ماژول آبجکت ZIP استفاده کنید. پسازآن، از متد ماژول ()writeZip برای ذخیره آرشیو در سیستم لوکال خود بهره ببرید.
1. فایل جدید createArchive.js را در ویرایشگر متن دلخواهتان ایجاد و آن را باز کنید. در این مقاله، برای انجام این کار از کامند لاین nano استفاده خواهیم کرد:
nano createArchive.js
2. سپس، از require در ماژول adm-zip در فایل createArchive.js استفاده کنید:
const AdmZip = require("adm-zip");
3. ماژول adm-zip کلاسی را ارائه میدهد که حاوی شیوههایی برای ایجاد ZIP Archive است. ازآنجاکه در طول فرایند آرشیو با فایلهای حجیم مواجه میشوید، ممکن است تا زمانی که آرشیو ZIP ذخیره نشود، استرینگ اصلی را مسدود کنید. برای نوشتن کد غیرمسدودکننده، تابعی ناهمگام را برای ایجاد و ذخیره ZIP Archive تعریف کنید.
برای آموزش کامل نصب Node.js در اوبونتو مقاله زیر را از دست ندهید.
4. در فایل createArchive.js خود، کد هایلایتشده زیر را اضافه کنید:
const AdmZip = require("adm-zip"); async function createZipArchive() { const zip = new AdmZip(); const outputFile = "test.zip"; zip.addLocalFolder("./test"); zip.writeZip(outputFile); console.log(`Created ${outputFile} successfully`); } createZipArchive();
5. createZipArchive تابعی ناهمگام (Asynchronous Function) است که ZIP Archive را از دایرکتوری مشخصی ایجاد میکند. چیزی که آن را ناهمگام میکند، کلمه کلیدی async است که قبل از برچسب تابع تعریف کردهاید.
6. اکنون در داخل تابع، نمونهای از ماژول adm-zip ایجاد کنید که متدهایی را ارائه کند تا بتوانید برای خواندن و ایجاد آرشیو استفاده کنید. هنگامی که نمونهای ایجاد میکنید، adm-zip یک ZIP درون حافظه ایجاد میکند که در آن، میتوانید فایلها یا دایرکتوریها را اضافه کنید.
7. در مرحله بعد، نام آرشیو را تعریف و آن را در متغیر outputDir ذخیره کنید. برای افزودن دایرکتوری test به آرشیو درون حافظه، متد ()addLocalFolder را از adm-zip با Path دایرکتوری بهعنوان آرگومان فراخوانی کنید.
8. پس از اضافهشدن دایرکتوری، شما باید متد ()writeZip را از adm-zip با متغیری حاوی نام ZIP Archive فراخوانی کنید. متد ()writeZip آرشیو را در دیسک لوکال شما ذخیره میکند.
9. پس از انجام این کار، با فراخوانی ()console.log تأیید کنید که فایل ZIP با موفقیت ایجاد شده است.
10. درنهایت، تابع ()createZipArchive را فراخوانی کنید. قبل از اجرای فایل، کد را در بلوک try…catch بستهبندی کنید تا خطاهای زمان اجرا مدیریت شود:
const AdmZip = require("adm-zip"); async function createZipArchive() { try { const zip = new AdmZip(); const outputFile = "test.zip"; zip.addLocalFolder("./test"); zip.writeZip(outputFile); console.log(`Created ${outputFile} successfully`); } catch (e) { console.log(`Something went wrong. ${e}`); } } createZipArchive();
11. در داخل بلوک try، کد سعی میکند ZIP Archive را ایجاد کند. درصورت موفقیتآمیزبودن، تابع ()createZipArchive با پرش از بلوک catch خارج میشود. اگر ایجاد ZIP Archive باعث خطا شود، تابع در بلوک catch متوقف و خطا در کنسول ثبت خواهد شد.
12. با CTRL + X فایل را در nano ذخیره کنید و از آن خارج شوید. برای ذخیره تغییرات، y را وارد کنید و با فشاردادن Enter در ویندوز یا کلید RETURN در مک، فایل را ثبت کنید.
13. سپس، فایل createArchive.js را با استفاده از دستور node اجرا کنید:
node createArchive.js
14. اکنون، خروجی زیر را دریافت خواهید کرد:
Output Created test.zip successfully
15. سپس، محتویات دایرکتوری را فهرست کنید تا ببینید آیا ZIP Archive ایجاد شده است یا خیر:
ls
16. درادامه، خروجی زیر را دریافت خواهید کرد که آرشیو را در میان مطالب نشان میدهد:
Output createArchive.js node_modules package-lock.json package.json test test.zip
17. با تأیید اینکه ZIP Archive ایجاد شده است، آرشیو و اندازه فایل دایرکتوری test را باهم مقایسه کنید تا ببینید فشردهسازی کار میکند یا خیر. اندازه دایرکتوری test را با استفاده از کامند du بررسی کنید:
du -h test
18. فلاگ h- به du دستور میدهد که اندازه دایرکتوری را در قالب human-readable نشان دهد. پس از اجرای کامند، خروجی زیر را دریافت خواهید کرد:
Output 15M test
19. سپس، اندازه فایل آرشیو test.zip را بررسی کنید:
du -h test.zip
20. کامند du خروجی زیر را ثبت میکند:
Output 760K test.zip
21. همانطورکه میبینید، ایجاد فایل ZIP اندازه دایرکتوری را از ۱۵ مگابایت (MB) به ۷۶۰ کیلوبایت (KB) کاهش داده است. در این مرحله، ZIP Archive را ایجاد کردید. حالا میتوانید محتویات فایل زیپ را فهرست کنید. در مرحله بعد، به شما آموزش خواهیم داد که چگونه میتوانید این کار را انجام دهید.
مرحله ۳. فهرستکردن فایلها در ZIP Archive
در این مرحله، با استفاده از adm-zip تمام فایلهای موجود در ZIP Archive را فهرست خواهید کرد. برای انجام این کار، باید ماژول adm-zip را با مسیر ZIP Archive خود نمونهسازی کنید. سپس، متد ماژول ()getEntries را فراخوانی کنید که آرایهای از اشیاء را برمیگرداند. هر آبجکت، اطلاعات مهمی درباره یک آیتم در آرشیو بههمراه دارد.
1. برای فهرستکردن فایلها، روی آرایه تکرار کنید تا به filename از هر آبجکت دسترسی پیدا کنید. سپس، آن را در کنسول وارد کنید. readArchive.js را در ویرایشگر متن دلخواه خود ایجاد و باز کنید:
nano readArchive.js
2. در readArchive.js خود، برای خواندن و فهرستکردن محتویات ZIP Archive از کد زیر استفاده کنید:
const AdmZip = require("adm-zip"); async function readZipArchive(filepath) { try { const zip = new AdmZip(filepath); for (const zipEntry of zip.getEntries()) { console.log(zipEntry.toString()); } } catch (e) { console.log(`Something went wrong. ${e}`); } } readZipArchive("./test.zip");
3. ابتدا، از require در ماژول adm-zip استفاده کنید. سپس تابع ()readZipArchive را تعریف کنید که تابعی ناهمگام است.
4. در داخل تابع، نمونهای از adm-zip را با مسیر فایل ZIP که میخواهید آن را بخوانید، ایجاد کنید. حال مسیر فایل را پارامتر filepath ارائه میدهد و adm-zip فایل را میخواند و آن را تجزیه میکند.
5. پس از خواندن آرشیو، عبارت for…of تعریف کنید تا روی اشیاء در آرایهای تکرار شود و متد ()getEntries از adm-zip را هنگام فراخوانی برگرداند. در هر تکرار، آبجکتی به متغیر zipEntry اختصاص داده میشود. در داخل حلقه (loop)، آبجکت را به استرینگی تبدیل کنید تا آن را با استفاده از متد ()Node.js toString نشان دهد. سپس با استفاده از متد ()console.log، آن را در کنسول وارد کنید.
برای آموزش نصب و راهاندازی Node.js در ویندوز سرور 2019 مقاله زیر را از دست ندهید.
6. درادامه، تابع ()readZipArchive را با مسیر فایل Archive ZIP بهعنوان آرگومان فراخوانی کنید. پسازآن، فایل خود را ذخیره کنید و از آن خارج شوید و دوباره فایل را با کامند زیر اجرا کنید:
node readArchive.js
7. خروجیای مشابه با موارد زیر را دریافت خواهید کرد (ویرایششده برای اختصار):
Output { "entryName": "file1.txt", "name": "file1.txt", "comment": "", "isDirectory": false, "header": { ... }, "compressedData": "<27547 bytes buffer>", "data": "<null>" } ...
8. کنسول چهار آبجکت را ثبت میکند. هر فایل در آرشیو با آبجکتی شبیه به آنچه در خروجی قبلی است، نشان داده میشود. بهمنظور دریافت نام فایل برای هر فایل، باید به ویژگی name دسترسی داشته باشید.
9. در فایل readArchive.js، کد هایلایتشده زیر را برای دسترسی به هر نام فایل اضافه کنید:
const AdmZip = require("adm-zip"); async function readZipArchive(filepath) { try { const zip = new AdmZip(filepath); for (const zipEntry of zip.getEntries()) { console.log(zipEntry.name); } } catch (e) { console.log(`Something went wrong. ${e}`); } } readZipArchive("./test.zip");
10. ویرایشگر متن خود را ذخیره کنید و از آن خارج شوید. حالا با کامند node دوباره فایل را اجرا کنید:
node readArchive.js
11. با اجرای فایل، خروجی زیر حاصل میشود:
Output file1.txt file2.txt file3.txt underwater.png
12. اکنون، خروجی نام فایلها را در Archive ZIP ثبت میکند. حال میتوانید هر فایل را در Archive ZIP بخوانید و فهرست کنید. در بخش بعدی، فایلی را به Archive ZIP موجود اضافه خواهید کرد.
مرحله ۴. افزودن فایل به آرشیو موجود
در این مرحله، فایلی ایجاد و بدون استخراج آن را به Archive ZIP اضافه کنید که قبلاً ایجاد کردهاید. ابتدا، باید با ایجاد نمونه adm-zip ،Archive ZIP را بخوانید. سپس، از متد ماژول ()addFile برای اضافهکردن فایل در ZIP استفاده کنید. درنهایت، بایگانی ZIP را در سیستم لوکال ذخیره کنید.
1. فایل file4.txt با dummy content ایجاد کنید که 600000 خط تکرار شده است:
yes "dummy content" | head -n 600000 > file4.txt
2. updateArchive.js را در ویرایشگر متن خود ایجاد و باز کنید:
nano updateArchive.js
3. require در ماژول adm-zip و ماژول fs، به شما امکان میدهد با فایلهای موجود در فایل updateArchive.js کار کنید:
const AdmZip = require("adm-zip"); const fs = require("fs").promises;
4. require در ورژن promise-based از ماژول fs، به شما امکان میدهد کدهای ناهمگام را بنویسید. هنگامی که یک متد fs را فراخوانی میکنید، یک promise را برمیگرداند.
5. سپس در فایل updateArchive.js خود، کد هایلایتشده زیر را برای افزودن فایل جدید به Archive ZIP اضافه کنید:
const AdmZip = require("adm-zip"); const fs = require("fs").promises; async function updateZipArchive(filepath) { try { const zip = new AdmZip(filepath); content = await fs.readFile("./file4.txt"); zip.addFile("file4.txt", content); zip.writeZip(filepath); console.log(`Updated ${filepath} successfully`); } catch (e) { console.log(`Something went wrong. ${e}`); } } updateZipArchive("./test.zip");
6. updateZipArchive تابعی ناهمگام است که فایلی را در filesystem میخواند و آن را به ZIP موجود اضافه میکند. در تابع، شما باید نمونهای از adm-zip را با path فایل Archive ZIP در filepath بهعنوان پارامتر ایجاد کنید.
7. در مرحله بعد، متد ()readFile ماژول fs را برای خواندن فایل در filesystem فراخوانی کنید. متد ()readFile یک promise را برمیگرداند که شما باید با کلمه کلیدی await آن را رفع کنید (wait فقط در asynchronous functions معتبر است). پس از حلشدن، متد یک buffer object را برمیگرداند که حاوی محتویات فایل است.
8. سپس، متد ()addFile را از adm-zip فراخوانی کنید. این متد دو آرگومان میگیرد: آرگومان اول نام فایلی است که میخواهید به آرشیو اضافه کنید و آرگومان دوم آبجکت buffer و حاوی محتویات فایلی است که متد ()readFile را فرامیخواند.
9. پسازآن، متد ()writeZip ماژول adm-zip را برای ذخیره و نوشتن تغییرات جدید در Archive ZIP فراخوانی کنید. پس از انجام این کار نیز، متد ()console.log را برای ثبت پیام موفقیتآمیز فراخوانی کنید.
10. درنهایت، تابع ()updateZipArchive را با مسیر فایل Archive ZIP بهعنوان آرگومان فراخوانی کنید. درادامه، فایل خود را ذخیره کنید و از آن خارج شوید و بعدازآن، دوباره فایل updateArchive.js را با کامند زیر اجرا کنید:
node updateArchive.js
11. خروجی را بدینصورت خواهید دید:
Output Updated ./test.zip successfully
12. اکنون، تأیید کنید که Archive ZIP حاوی فایل جدید است. فایل readArchive.js را اجرا کنید تا محتویات Archive ZIP را با دستور زیر فهرست کنید:
node readArchive.js
13. حال خروجی زیر را دریافت خواهید کرد:
file1.txt file2.txt file3.txt file4.txt underwater.png
14. این تأیید میکند که فایل به ZIP اضافه شده است. اکنون میتوانید فایلی را به آرشیو موجود اضافه کنید. در بخش بعدی، آرشیو را دریافت خواهید کرد.
مرحله ۵. دریافت یک Zip Archive
در این مرحله، تمام محتویات Archive ZIP را میخوانید و در دایرکتوری دریافت میکنید. برای استخراج Archive ZIP، ابتدا باید adm-zip را با Path فایل آرشیو نمونهسازی کنید. پسازآن، متد ماژول ()ExtractAllTo را با نام دایرکتوریای فراخوانی کنید که میخواهید محتوای ZIP استخراجشده شما در آن قرار گیرد.
1. ExtractArchive.js را در ویرایشگر متن خود ایجاد و باز کنید:
nano extractArchive.js
2. از require در ماژول adm-zip و از ماژول path در فایل extractArchive.js استفاده کنید:
const AdmZip = require("adm-zip"); const path = require("path");
3. ماژول path متدهای مفیدی را برای برخورد با مسیرهای فایل ارائه میدهد. در فایل extractArchive.js خود، کد هایلایتشده زیر را برای استخراج آرشیو اضافه کنید:
const AdmZip = require("adm-zip"); const path = require("path"); async function extractArchive(filepath) { try { const zip = new AdmZip(filepath); const outputDir = `${path.parse(filepath).name}_extracted`; zip.extractAllTo(outputDir); console.log(`Extracted to "${outputDir}" successfully`); } catch (e) { console.log(`Something went wrong. ${e}`); } } extractArchive("./test.zip");
4. ()ExtractArchive تابعی ناهمگام است که پارامتری حاوی مسیر فایل Archive ZIP را میگیرد. در داخل تابع، شما باید adm-zip را با مسیر فایل Archive ZIP ارائهشده پارامتر filepath نمونهسازی کنید.
5. سپس، باید template literal تعریف کنید. در داخل template literal (${})، متد ()parse را از ماژول path با مسیر فایل فراخوانی میکنید. متد ()parse یک آبجکت را برمیگرداند.
6. برای دریافت نام فایل ZIP بدون پسوند فایل، ویژگی name را به آبجکتی اضافه کنید که متد ()parse برمیگرداند. هنگامی که نام بایگانی برگردانده شد، template literal مقدار را با استرینگ extracted_ درونیابی میکند. سپس value، در متغیر outputDir ذخیره میشود. این نام دایرکتوری استخراجشده خواهد بود.
7. در مرحله بعد، متد ExtractAllTo ماژول adm-zip را با نام دایرکتوری ذخیرهشده در outputDir فراخوانی کنید تا محتویات موجود در فهرست را دریافت کنید. بعدازآن، برای ثبت پیام موفقیتآمیز، ()console.log را فراخوانی کنید.
8. درنهایت، تابع ()extractArchive را با مسیر Archive ZIP فراخوانی کنید. فایل خود را ذخیره کنید و از ویرایشگر خارج شوید. درادامه، فایل extractArchive.js را با کامند زیر اجرا کنید:
node extractArchive.js
9. اکنون خروجی زیر را دریافت خواهید کرد:
Output Extracted to "test_extracted" successfully
10. تأیید کنید که دایرکتوری حاوی محتویات ZIP ایجاد شده است:
ls
11. سپس، خروجی زیر را دریافت خواهید کرد:
Output createArchive.js file4.txt package-lock.json readArchive.js test.zip updateArchive.js extractArchive.js node_modules package.json test test_extracted
12. اکنون، به دایرکتوری حاوی محتویات استخراجشده بروید:
cd test_extracted
13. فهرست مطالب در دایرکتوری زیر قرار دارد:
ls
14. درنهایت خروجی زیر را دریافت خواهید کرد:
Output file1.txt file2.txt file3.txt file4.txt underwater.png
15. اکنون، میتوانید ببینید که دایرکتوری تمام فایلهایی را دارد که در دایرکتوری اصلی بودند. بدینترتیب، محتوای Archive ZIP را در دایرکتوری استخراج کردهاید.
جمعبندی
با افزایش حجم فایلها، بخش زیادی از فضای هارددیسک اشغال میشود؛ درنتیجه، مجبوریم منابع سرور خود را افزایش دهیم. ازاینرو، بسیاری از توسعهدهندگان ترجیح میدهند بهجای صرف هزینه اضافی، از ماژول adm-zip برای فشردهکردن فایلهایشان استفاده کنند.
در این مقاله از وبلاگ پارس پک، نحوه کار با فایل فشرده در Node.js را گامبهگام آموزش دادیم. با کمک این آموزش، میتوانید فایلهای سنگین خود را بهراحتی فشرده و ذخیره کنید. اگر سؤال و مشکلی درزمینه نحوه کار با Archive ZIP در Node.js داشتید، با ما بهاشتراک بگذارید تا کارشناسان ما شما را راهنمایی کنند.
سؤالات متداول
۱. چگونه فایل ZIP را در Node از حالت فشرده خارج کنیم؟
- با استفاده از Node.js، اپلیکیشنی برای زیپ یا بازکردن فایلها ایجاد کنید.
- ماژول Express-easy-zip را برای فشردهسازی فایلها یا فهرستها نصب کنید.
- ماژول unzip NodeJS را نصب کنید تا فایل از حالت فشرده خارج شود.
۲. چگونه فایل ZIP را در Node.js بخوانیم؟
ابتدا به ماژول adm-zip نیاز دارید. سپس، تابع ()readZipArchive را تعریف کنید که تابعی ناهمگام است. اکنون در تابع، نمونهای از adm-zip را با مسیر فایل ZIP که میخواهید بخوانید، ایجاد کنید.