آپلود فایل در PHP

در اکثر اسکریپت‌ها نیاز به آپلود فایل داریم. این کار در PHP بسیار ساده است اما نیازمند به‌کارگیری ترفندها و خلاقیت در اجراست! در این آموزش علاوه بر یادگیری مراحل آپلود در PHP، سه ترفند و ۲ نکته برای اجرای سیستم‌های واقعی را می‌آموزید.

فرقی ندارد قرار است چه نوع فایلی را در سایتتان آپلود کنید، با این روش هر فرمتی را می‌توانید upload کنید.

بدون مقدمه وارد بحث می‌شوم. ابتدا یک فرم آپلود ساده ایجاد می‌کنیم. سپس با دستورها و متغیرهایی برای آپلود، پردازش و ذخیره کردن فایل آشنا خواهیم شد. در انتها نیز ترفندها و نکات را بررسی می‌کنیم.

فرم html آپلود فایل

در ابتدا باید یک فرم برای انتخاب و ارسال فایل به سرور را در صفحه HTML خود ایجاد کنیم. این فرم مشابه فرم‌های PHP است که قبلاً ایجاد کرده‌ایم با دو تفاوت اصلی:

  1. نوع enctype فرم
  2. نوع فیلد input برای آپلود فایل

ابتدا کد زیر را بررسی کنید تا جزئیاتش را توضیح دهم:

<form action="upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="my_file">
    <input type="submit" name="submit" value="آپلود فایل">
</form>

متد ارسالی برای این فرم حتماً باید از نوع POST باشد. آپلود فایل در حالت GET عمل نمی‌کند. اگر تفاوت این دو روش و کاربردهایشان اطلاع ندارید، آموزش ارسال get و post در PHP را ببینید.

دو تفاوتی که بالاتر اشاره کردم در قطعه کد بالا مشخص است:

  • فیلد enctype از نوع multipart/form-data است.
  • نوع فرمت فیلد ما file است.

در پایان هم یک دکمه (Button) برای ارسال فرم در نظر گرفته‌ام. می‌توانید آن را به هر شکل دیگری نیز ایجاد کنید.

پس از ارسال این فرم، اطلاعات به فایلی به نام upload.php در کنار فایل حاوی همین فرم ارسال می‌شود. کار اصلی ما (پردازش و ذخیره فایل آپلودی) در دومی است.

دریافت فایل آپلود شده و مشخصات آن در PHP

یک متغیر سراسری PHP به نام $_FILES داریم که اطلاعات فایل آپلودی را نگهداری می‌کند. اگر در یک فرم چند فیلد از نوع file داشته باشیم، همهٔ آن‌ها در همین متغیر قرار می‌گیرند.

متغیر $_FILES یک آرایه دوبعدی یا به‌نوعی یک ماتریس است. در اولین سطح فایل‌ها قرار می‌گیرند. (با کلید مشابه ویژگی name در فیلد input) در سطح دوم مشخصات مربوط به هر فایل وجود دارد.

برای دسترسی به نام فایل در مثال، باید $_FILES["my_file"]["name"] را فراخوانی کنیم؛ چون نام فیلد در فرم my_file است.

اگر با آرایه‌ها آشنایی ندارید، در جلسه آرایه در PHP با این ساختار پرکاربرد و ترفندهایش آشنا می‌شوید.

به ازای هر فایل، پنج ویژگی در اختیار داریم:

  • name : نام واقعی فایل آپلود شده (نام فایل روی سیستم کاربر)
  • type : فرمت MIME فایل را مشخص می‌کند (مثلاً image/jpeg برای عکس‌های jpg یا jpeg)
  • tmp_name : مسیر و نام فایل آپلودشده در سرور
  • error : ارور در هنگام آپلود فایل (0 به معنای عدم خطا)
  • size : حجم فایل به بایت (byte)

وقتی ارسال فرم برای آپلود فایل در PHP انجام می‌شود، این فایل‌ها با یک نام موقت در یک مسیر موقت (اصطلاحاً temp directory) در سرور ذخیره می‌شوند. حالا باید خودمان آن را در مسیر و با نام دلخواهمان ذخیره کنیم. (جلوتر یاد می‌گیریم چطور!)

تابع basename در php

تابع basename() به ما کمک می‌کند تا نام یک فایل را راحت‌تر متوجه شویم. این تابع PHP مسیر یک فایل را از ما می‌گیرد و نام آن (به همراه فرمتش) را به ما برمی‌گرداند.

یک پارامتر ورودی دوم نیز می‌توانیم برایش تعریف کنیم. (اختیاری) درصورتی که فرمت فایل (extension) برابر مقدار مشخص‌شده در این پارامتر باشد، آن را از مقدار خروجی حذف می‌کند.

برای درک بهتر، فرض کنید فایلی به نام sabzdanesh.jpg دارم که در مسیر /public قرار دارد. حالت‌های مختلف فراخوانی این تابع و خروجی آن را در باکس کد زیر مشخص کرده‌ام:

<?php
$file_path = "/public/sabzdanesh.jpg";

echo basename( $file_path );           // sabzdanesh.jpg
echo basename( $file_path, ".jpg" );   // sabzdanesh
echo basename( $file_path, ".pdf" );   // sabzdanesh.jpg

بنابراین با صدا زدن این تابع روی ویژگی نام فایل آپلودشده، نام آن را خواهیم داشت:

basename( $_FILES["myFile"]["name"] );

ذخیره کردن فایل آپلود شده

حال که به فایل و اطلاعات آن دسترسی پیدا کردیم، باید آن را در مسیر دلخواهمان در سرور ذخیره کنیم. تابعی با نام move_uploaded_file() داریم که دو پارامتر به‌عنوان ورودی می‌گیرد:

  1. پارامتر اول، مشخص‌کننده مسیر و نام فایل فعلی است. (که در آپلود فایل PHP در پوشه موقت قرار دارد.)
  2. پارامتر دوم، مشخص‌کننده مسیر و نام فایل پس از ذخیره‌سازی است. (محل و نامی که می‌خواهیم ذخیره شود.)

من در این آموزش فایل‌های آپلود شده را در مسیر /files در کنار کدهایم قرار می‌دهم. شما می‌توانید هر مسیر دیگر حتی خارج از فولدر فعلی را تعیین کنید.

کد زیر، یک شیوه ساده برای ذخیره کردن فایل آپلودی در PHP است:

<?php
$file_name = basename($_FILES["image"]["name"]);

$file_temp = $_FILES["image"]["tmp_name"];

move_uploaded_file( $file_temp, "files/".$file_name );

بعد از اجرای این قطعه کد، فایل با همان نامی که در کامپیوتر کاربر بوده در مسیر موردنظرمان ذخیره می‌شود.

تابع move_uploaded_file() یک مقدار بولین به‌عنوان خروجی به ما می‌دهد. در نتیجه می‌توانیم وضعیت عملیات ذخیره‌سازی را با یک شرط if در PHP بررسی کنیم.

کار با ویژگی‌های فایل آپلود شده

احتمالاً تا الآن حدس زده باشید که فرآیند آپلود در PHP و ذخیره‌سازی آن در اکثر سیستم‌های آنلاین کمی پیچیده‌تر و کامل‌تر از این آموزش است. اما پایه همه آن‌ها دقیقاً مشابه همین کاری است که با هم انجام دادیم. 🙂

د این بخش ۳ ترفند در کار با ویژگی‌های file آپلودی در PHP را با هم بررسی می‌کنیم. می‌توانید از این ترفندها برای هدفی که دارید الگوبرداری کنید.

بررسی فرمت فایل آپلود شده

برای این کار باید MIME Type فایل را بررسی کنیم. البته MIME Type مقادیر اضافه‌تری علاوه بر فرمت را نیز دارد.با جستجوی عبارت «mime types list» لیست این اسامی را برای فرمت‌های موردنظرتان پیدا می‌کنید.

اگر می‌خواهید فرمت فایل را از روی نام آن محاسبه کنید، دو راه‌حل به شما پیشنهاد می‌کنم:

در روش اول، نام فایل را به کاراکتر . (جداکننده نام و فرمت) تکه تکه کرده و آخرین تکه را به عنوان فرمت فایل استخراج می‌کنیم؛ مشابه کد زیر:

$file_extension = strtolower( end( explode( ".", $_FILES["image"]["name"] ) ) );

تابع explode() برای جدا کردن نام و فرمت و strtolower() برای تبدیل حروف به حروف کوچک است. این توابع و چند تابع کاربردی دیگر در جلسه آموزش رشته در PHP معرفی و بررسی شده‌اند.

روش دوم استفاده از تابع basename() روی ویژگی MIME Type است. این تابع مقدار ورودی را شبیه یک آدرس می‌بیند و بخش آخر (که بعد از آخرین / است) را به‌عنوان خروجی بازمی‌گرداند؛ دقیقاً همان چیزی که دنبالش هستیم! 😉

$file_extension = basename($_FILES["myFile"]["type"]);

MIME Type ها دوبخشی هستند؛ یعنی ساختاری شبیه type/subtype دارند. اولی یک دسته‌بندی بزرگ‌تر (مثلاً عکس، صدا و …) و دومی متناسب با فرمت (مثلاً jpg، mp3) مشخص می‌شود.

حجم فایل آپلودی در PHP

برای دسترسی به حجم فایلی که آپلود شده، فقط باید ویژگی size را بررسی کنیم. یادتان باشد که این حجم به‌صورت عددی و با مقیاس بایت نمایش داده می‌شود. در ساختار شرطی زیر، بررسی کرده‌ام که آیا حجم فایل کمتر از 500 کیلوبایت است یا نه؟

if ($_FILES["myFile"]["size"] < 500000){ //less than 500KB

    //uplaod File

}else{

    //Show Error!

}

بررسی موجود بودن فایل همنام با فایل آپلود شده

اگر فایل مقصدی که به عنوان ورودی دوم به تابع move_uploaded_file() داده‌ایم از قبل موجود باشد، فایل جدید جایگزین آن می‌شود! بنابراین بهتر است همیشه مراقب بازنویسی فایل‌ها و حذف فایل‌های قبلی در آپلود PHP باشید.

برای بررسی اینکه فایلی با نام مشخص در یک مسیر خاص وجود دارد یا نه، از تابع file_exists() در PHP استفاده می‌کنیم.

<?php
// check file exists in PHP
file_exists( "files/test-from-sbzd.pdf" );

// check with variable
$file_name = "sabzdanesh.mp3";
file_exists( "files/" . $file_name );

اگر مقدار خروجی این تابع true بود، یعنی فایلی با این نام در مسیر مورد نظر وجود دارد. (true و false یک مقدار بولین است که در جلسه متغیر PHP و انواع داده معرفی شده‌اند.)

در آپلود چند فایل می‌توانید از ساختار حلقه PHP کمک بگیرید. چند مثال از این مورد در صفحه مستنداتش وجود دارد.

آپلود در PHP در دنیای واقعی!

اگر در حال ایجاد یک سیستم غیر آزمایشی برای آپلود فایل هستید، در این بخش نکاتی به شما می‌گویم که بهتر است به آن‌ها توجه کنید.

در سیستم‌های تحت وب بزرگ که تعداد فایل‌های آپلود شده زیاد هستند، قطعاً بسیار زیاد به فایل‌های همنام بر می‌خوریم. پیشنهاد می‌کنم در این مورد برنامه‌ریزی و فکر کنید. برای اینکه ایده بگیرید، چند روش ساده اما پراستفاده را مطرح می‌کنم:

  • یک نام تصادفی برای فایل انتخاب کنید. در آموزش ساخت شناسه منحصربه‌فرد در PHP با روش‌های هش PHP، ترفندهای کار با رشته و توابع زمان در PHP روش‌های مختلفی را بررسی کرده‌ایم.
  • اگر هر کاربر فقط یک فایل در سیستم شما دارد، شاید بهتر باشد نام کاربری او را به عنوان نام فایل انتخاب کنید. (مثل عکس پروفایل)
  • متناسب با تحلیل سیستم، اختصاص یک مسیر (فولدر) مشخص برای فایل‌های هر کاربر نیز می‌تواند ایده مناسبی باشد.
  • ترکیب این روش‌ها را هم می‌توانید استفاده کنید. مثلاً علاوه بر تخصیص یک فولدر اختصاصی به هر کاربر، تاریخ یا زمان آپلود را با نام اصلی فایل ترکیب کنید.

در این آموزش با روند آپلود در PHP و چند ترفند کاربردی آشنا شدید. اگر می‌خواهید توابع اصلی و این روند را به خاطر بسپارید، همین الآن سعی کنید یک سیستم آپلود ساده ایجاد کنید.

اگر سؤال یا تجربه‌ای در این مورد دارید، از بخش دیدگاه‌ها با ما و دوستانتان مطرح کنید. 🙂

این آموزش بخشی از یک آموزش جامع و قدم به قدم در سبز دانش است: دوره رایگان آموزش PHP