
آپلود فایل ها بخش ضروری اکثر برنامه های تحت وب است و مهم است که آپلود فایل را به طور موثر انجام دهیم، به خصوص اگر قصد داریم فایل های حجیم را آپلود کنیم.
پیش از این نوشته مفصلی منتشر کردم که تاپیکهای مربوط به کارکردن با فایل ها در لاراول رو پوشش میداد..
در این نوشته میخوايم آپلود فایل های حجیم رو بررسی کنیم.. در واقع این نوشته مکملی هست بر نوشته اول که درش مکانیزم نسبتا پیشرفته تری رو استفاده میکنیم.
زبان PHP پروسه نسبتا سر راستی رو برای آپلود فایل ها داره.. در واقع با هر مرورگری که با RFC-1867 سازگار باشه، میتونید به راحتی اقدام به ارسال فایل ها به سمت سرور کنید. یه سری توابع پیش فرض هم موجود هست که لاراول در پشت پرده از اونها استفاده میکنه و کار شما رو راحت تر میکنه..
به این ترتیب با استفاده از کلاس Request در لاراول به راحتی میتونید فایل هاتون رو روی هر دیسکی که خواستید آپلود کنید..
اما در پشت پرده چه اتفاقی میفته...
نوع درخواست HTTP ای که برای ارسال فایل ها باید استفاده کنید POST هست، هر چند که درخواست PUT هم قابل استفاده است. دو گزینه در تنظیمات PHP وجود داره که اثر مستقیم روی این درخواست ها داره..
اولی گزینه upload_max_filesize هست که یک مقدار بر حسب مگابایت میگیره و آستانه حجم فایل های آپلودی رو مشخص میکنه.
دومی گزینه post_max_size هست که حجم فایل های ارسالی توسط درخواست POST رو مشخص میکنه.
پس بالا بردن این مقادیر تا حد زیادی میتونه محدودیت رو برطرف کنه.
از طرف دیگه PHP یک زبان تفسیری هست که گزینه دیگری در تنظیماتش داره که آستانه زمان اجرا رو مشخص میکنه. گزینه max_execution_time مقداری رو بر حسب ثانیه دریافت میکنه و اگر اجرای کدها بیش از اون زمان ببره، پروسس رو از بین میبره... پس افزایش این گزینه هم برای فایل های بزرگ گزینه دیگری هست که میتونه کمک کنه.
پس از گزینه های بالا به گزینه چهارم میرسیم که memory_limit هست و آستانه استفاده از حافظه رو مشخص میکنه.. ممکنه در ابتدا فکر کنید که ما داریم فایل رو روی دیسک ذخیره میکنیم و درست هم هست اما اگر قرار باشه پس از آپلود عملیات خاصی رو فایل ها انجام بدید (مثلا فرمت یه ویدیو رو عوض کنید) اینجاست که این گزینه هم اهمیت پیدا میکنه.
تغییر دادن گزینه های بالا تا حدی به پروسه آپلود فایل های حجیم کمک میکنه... اما موارد دیگه ای هم هست که باید بهشون توجه کرد.. مثلا وابسته به سرعت کانکشنی که دارید باهاش عملیات آپلود رو انجام میدید، ممکنه مجبور بشید زمان اجرا رو خیلی بالا ببرید و این کار ممکنه روی سایر بخش ها اثر بگذاره. در عین حال هر گونه قطعی در اتصال شما و یا سرور باعث به وجود اومدن Timeout میشه و باید پروسه رو از ابتدا شروع کنید... پس میبینید که پروسه ای که قرار بود خیلی ساده باشه، در واقع به فاکتور های زیادی وابسته است.
یکی از روش های جالبی که میتونیم استفاده کنیم، چانک کردن فایل در سمت کلاینت و ارسال داده ها به سمت سرور هست. که میشه مرحله اول.. سپس مرج کردن قطعات فایل در سمت سرور هست، که میشه مرحله دوم.
در اینجا از کتابخونه جاوااسکریپتی resumable.js استفاده میکنیم..
در این مرحله یه فایل به نام upload.blade.php در پوشه resources/views میسازیم و یه باتن ساده با استفاده از بوت استرپ داخلش قرار میدیم. (برای ضمیمه کردن بوت استرپ بهتره از یه Layout استفاده کنید)

حالا کافیه تا اسکریپت مورد نظر برای اجرای آپلود رو ضمیمه کنیم. پس ابتدا در انتهای تگ body فایل js کتابخونه رو به همراه jQuery ضمیمه میکنیم:

و حالا اسکریپت مورد نطر برای استفاده از resumable رو قرار میدیم:

در این مرحله نیاز داریم تا ابتدا پکیج زیر رو با composer نصب کنیم:

در فایل blade ای که در مرحله قبل تعریف کردیم ، از پراپرتی کاستوم data-url ma استفاده کردیم و آدرس آپلود در سمت سرور رو مشخص کردیم.. و بعد هم در سمت کدهای جاوااسکریپت اون پراپرتی رو گرفتیم و به آبجکت Resumable پاس دادیم.. اما هنوز چنین آدرسی در پروژه لاراولی ما موجود نیست. پس قدم بعد ساخت یک کنترلر هست:

و حالا به فایل web.php در پوشه routes میریم و یک Route از نوع Post برای پروسه آپلود و یک Route از نوع View برای نمایش بلیدی که ساختیم تعریف میکنیم:

قدم بعد ساخت متد store در کنترلر UploadsController هست. داخل این متد ما از پکیجی که نصب کردیم استفاده میکنیم. در واقع ۳ حالت کلی در اینجا ممکنه اتفاق بیفته:
پروسه آپلود در حال انجام شدن باشه

در اینجا من برای نمایش حالات مختلف ذخیره فایل (روی دیسک های محلی و یا S3) از ۳ متد دیگه در کنترلر استفاده کردم، که اونها رو هم بررسی میکنیم.. (اما جای این متد ها در واقع داخل کنترلر نیست و من سر و سامان دادن به این موضوع رو به عنوان یک تمرین به خودتون میسپارم)
اگر آپلود فایل به پایان رسیده باشه میتونیم یکی از متدهای saveFile یا saveFileToS3 رو فراخوانی کنیم و فایل آپلود شده رو بهش پاس بدیم. ..


و در نهایت متد createFileName که یه اسم رندوم برامون میسازه

حال میتونید به آدرس upload/ در پروژه تون برید و آپلود فایل های حجیم رو امتحان کنید...
چنانچه نوشته رو دنبال کردید و مایل بودید، روش های تر و تمیز کردن کد ها رو به علاوه سایر روش های جالبی که برای این پروسه سراغ دارید رو در زیر پست کامنت کنید