در اکثر اسکریپتها نیاز به آپلود فایل داریم. این کار در PHP بسیار ساده است اما نیازمند بهکارگیری ترفندها و خلاقیت در اجراست! در این آموزش علاوه بر یادگیری مراحل آپلود در PHP، سه ترفند و ۲ نکته برای اجرای سیستمهای واقعی را میآموزید.
فرقی ندارد قرار است چه نوع فایلی را در سایتتان آپلود کنید، با این روش هر فرمتی را میتوانید upload کنید.
بدون مقدمه وارد بحث میشوم. ابتدا یک فرم آپلود ساده ایجاد میکنیم. سپس با دستورها و متغیرهایی برای آپلود، پردازش و ذخیره کردن فایل آشنا خواهیم شد. در انتها نیز ترفندها و نکات را بررسی میکنیم.
فهرست محتوای آموزش
فرم html آپلود فایل
در ابتدا باید یک فرم برای انتخاب و ارسال فایل به سرور را در صفحه HTML خود ایجاد کنیم. این فرم مشابه فرمهای PHP است که قبلاً ایجاد کردهایم با دو تفاوت اصلی:
- نوع enctype فرم
- نوع فیلد 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()
داریم که دو پارامتر بهعنوان ورودی میگیرد:
- پارامتر اول، مشخصکننده مسیر و نام فایل فعلی است. (که در آپلود فایل PHP در پوشه موقت قرار دارد.)
- پارامتر دوم، مشخصکننده مسیر و نام فایل پس از ذخیرهسازی است. (محل و نامی که میخواهیم ذخیره شود.)
من در این آموزش فایلهای آپلود شده را در مسیر /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
این آموزش برای همیشه رایگانه! میتونید با اشتراکگذاری لینک این صفحه از ما حمایت کنید یا با خرید یه فنجون نوشیدنی بهمون انرژی بدید!
میخوام یه نوشیدنی مهمونتون کنم
سلام وقت بخیر
ممنون از سایت خوبتون.
فایل در پوشه images پروژه نمیشینه و عکس هم هنگام فراخوانی محصول فقط اسمش میاد و تاریخ آپلود. اطلاعات هم در دیتا بیش ذخیره میشه ولی عکس خودش نمیاد و ذخیره هم تو پروژه نمیشه
ممنون
سلام
مطمئن بشید که اسکریپتتون اجازه (دسترسی) ایجاد فایل در مسیری که براش مشخص کردید رو داره. همینطور اگه روی سیستم عامل لینوکس هستید (یا پروژه رو به هاست منتقل کردید) فولدر موردنظر باید قابل نوشتن باشه.
سلام. من برای آپلود اطلاعات مشکل دارم. عکس رو به پوشه image انتقال میده اما بقیه اطلاعات توی دیتابیس نمیاد. مثلا نام محصول و… هیچ کدوم ذخیره نمیشه
سلام
این موردی که میگید احتمالاً مشکلی در آپلود نیست چون فایل رو با موفقیت جابهجا کرده. به نظر میرسه مشکل از ثبت اطلاعاتتون توی دیتابیس باشه.
خطایی نمیگیرید؟ جلسه کار با دیتابیس از دوره رایگان رو ببینید. ببینید داره درست عمل میکنه؟ خطایی توی اجرای کوئری نمیده؟
هیچ خطایی نداره. فعلا با معلمم در اتباطم تا بدونم مشکل کجاست
سلام چجوری میتونم فایل رو بصورت api به یک سرور دیگه ای منتقل کنم؟
سلام
میتونید در سرور مقصد، فایل رو از مبدأ دانلود کنید؛ مثلاً با curl.
سلام من از این دستور استفاده کردم، عکس در دیتابیس اضافه میشه اما در صفحه اصلی و پنل مدیریت نمایش داده نمیشه، میشه راهنماییم کنین
سلام
آدرس عکس رو چطور نمایش میدید؟ نسبی یا بر اساس آدرس سایت؟ پیشنهاد ما دومیه.
احتمالش کمه، ولی ساختار تگ img رو هم یه چک کنین موردی نداشته باشه.
ادرس دهیم به صورت نسبی هست و اصلا عکس در پوشه ای که ادرس میدم سیو نمیشه، ممکنه به غیر از آدرس دهی مشکل جای دیگه باشه؟ و اینکه ممکنه آدرس دهی بر اساس آدرس سایت ک فرمودید رو توضیح بدین واسم
عکس ذخیره نمیشه؟! پس مشکل از همینه! چون فایلی وجود نداره که بخواد نمایشش بده.
یه کاری کنید: اون تیکهی آپلود و ذخیره فایل (بدون ارتباط با دیتابیس) رو جداگانه توی یه فایل دیگه قرار بدید و تستش کنید. تا ببینید چرا فایل رو ذخیره نمیکنه. اگه درست شد، قسمت دیتابیس هم اضافه کنید که مطمئن باشید این قسمت درسته.
بعدش همون حالت نسبی آدرس بدید ببینید نمایشش میده یا نه.
آدرس سایت هم یعنی به جای نسبی (
/images/name.jpg
) آدرس کامل (sabzdanesh.com/images/name.jpg
) رو ایجاد کنید.ممنون از پاسخگوییتون، اوکی شد
سلام و خسته نباشید چطور به پوشه های دیگر میشه فایل را فرستاد
اگه در همون ابتدای آپلود میخواید چنین کاری رو انجام بدید که صرفاً آدرس مقصد رو بهصورت نسبی (نسبت به موقعیت فایل کد) وارد کنید. برای برگشت به فولدرهای قبلی از
../
استفاده کنید.اگر منظورتون بعد از آپلوده، معمولاً از تابع
rename()
در PHP استفاده میکنند.سلام و خسته نباشید فقط اینکه در یک فایل ذخیره می کنه آدرس را وارد کنیم کار نمی کنه میشه راهنمایی کنید
سلام
وقتی آدرس رو توی مرورگر میزنید خطایی میده بهتون؟ چه خطایی؟
و اینکه دقت کنید که فرمت فایل (مثلاً jpg) رو هم در اسمی که ذخیره میکنید تعریف کنید.
اگر کار کنه هم خطا میده و فقط داخل یک جا میفرسته
متأسفانه منظورتون رو متوجه نمیشم! چه چیزی خطا میده؟ تابع rename؟ چه خطایی میده بهتون؟
سلام ببخشید از شما خیلی خوب کار می کنه من زود نظر دادم سپاس از شما و ممنون از این آموزش خوبتون 🌹
سلامت باشی علی رضای عزیز
خوشحالیم که این آموزش برات کاربردی بوده
سلام کار نمی کنه
سلام . من اپلودم درست کار میکنه و در یک پوشه ذخیره میشهولی وقتی میخوام از دیتابیس فراخوانی کنم سایر اطلاعات و میاره ولی عکس رو نمیاره .از این دستور استفاده کردم
سلام
میشه دیتایی که توی دیتابیس ذخیره شده و فقط قسمت php بخش src عکس رو بفرستید؟ تا بتونیم بهتر راهنماییتون کنیم.
سلام. تو بخش نمایش اطلاعات کاربر ، چطوری میشه رمز عبورش رو نشون داد؟ من از تکنیک هشینگ استفاده کرده ولی توی صفحه مشخصات رمز رو به صورت هش شده نمایش میده.
و عکس کاربر رو هم نمایش نمیده. دنباله پیام قبلی که گفتم عکس از کاربر دریافت نمیکنه.
سلام
قاعدتاً رمزی که هش میشه نباید قابل برگشت باشه! 🙂 یعنی یکطرفه است.
سلام وقت بخیر .
من خیلی کار با php بلد نیستم و یه پروژه درسی تو مدت کم زدم و تو قسمت گرفتن مشخصات کاربر ، گرفتن عکس کاربر و تاریخ تولد به شمسی هست. هرکاری می کنم عکس بارگزاری شده توی دیتابیس ذخیره نمیشه و تاریخ تولد هم شمسی نمیشه و میلادی هست.
اگر امکانش هست ممنون میشم بنده رو راهنمایی بفرمائید.
سلام
برای ذخیره عکس چه کاری انجام میدید؟ معمولاً فایل رو در جایی ذخیره میکنن و اسمش رو در دیتابیس ثبت میکنند تا بشه شناساییش کرد.
برای تاریخ شمسی هم میتونید از کتابخونه jdf کمک بگیرید. البته پیشنهاد میکنم زمان رو در دیتابیس به میلادی ذخیره کنید و موقع نمایش تبدیل کنید. در یکی از جلسات دوره رایگان درمورد کار با زمان میلادی صحبت کردیم.
سلام مجدد، ممنونم از پاسختون؛
توی فرم از input استفاده کردم و توی کد قسمت بکند کوئری insert زدم. حقیقتش اموزشهاتون دیدم ولی چون کامل php بلد نیستم بیشتر گیج شدم چطوری ربطش بدم به برنامم؟!
توی فرم هرچی زدم ذخیره میشه جز عکس. تاریخم حتی میلادیاش ذخیره میشه ولی شمساش نه. Jdf چطوری باید توی فرم اعمال بشه؟ من از datepicker استفاده کردم متاسفانه کاربردی نداشت.
حقیقتش تا جمعه وقت دارم پروژه رو برای استادم بفرستم 🙁 دقیقه ۹۰ مشخص کردن بکند حتما باید با php باشه.
این دوتا ایراد بنده بود توی پروژه ام.
اول از همه پیشنهاد میکنم اگه آشنایی ندارید، بخش به بخش پیاده کنید و بعدش در کنار هم قرار بدید. مثلاً آپلود فایل رو جداگانه ایجاد کنید، اگر صحیح عمل کرد، به فرم در اسکریپت اصلی اضافهاش کنید.
تاریخ میلادی که ذخیره شده رو وقتی فراخوانی میکنید، یک رشته متنی یا در بهترین حالت یه شیء زمان هست. در jdf توابعی هست که این مقدار رو بهش بدید و معادل شمسی اون رو بهتون بده. جستجو کنید «کتابخانه jdf» سایتی با همین نام هست که مستندات استفادش رو داره.
در اینجا هم پیشنهاد میکنم اول تبدیل زمان رو انجام بدید، اگه اوکی شد، datepicker رو بهش اضافه کنید. در نهایت میتونید در کنار فرم قرارش بدید.
سلام ، من فرم ثبت نام رو میخوام ثبت کنم به این قطع کد بالا “مربوط به ذخیره عکس “ارور می گیره. شما اشکالش میدونید چیه؟
سلام
کدتون برای آپلود صحیحه. ما روی یه فرم ساده هم تست کردیم و فایل رو بهدرستی انتقال داد. چه خطایی میگیرید؟
سلام این ها ارورهای مربوط به بخش دریافت عکس توی فرم ثبت نام هستند
دقت کنید که تابع
move_uploaded_file()
دو تا ورودی میگیره؛ اولی آدرس فعلی و دومی مسیر و اسمی که قرار ذخیره بشه. از خطا اینطور برداشت میشه که فقط مسیر ذخیره رو مشخص کردید.همینطور چک کنید که فولدر image از همون ابتدا کنار فایلتون وجود داشته باشه.
سلام وقت بخیر
نظر من حذف شد
گفته بودم یک اسکریپت شبکه اجتماعی دارم
کاربر میتونه عکس و ویدئو پست کنه
برای اینکه امکان اپلود موزیک در پست ها برای کاربر فرهم بشه باید چه کدی رو به کدی که فرمودید اضافه کنم
مبتدی هستم
لطفا راهنمایی کنید
ممنون
سلام
نه نظرتون حذف نشده بود و روز گذشته پاسخ داده شده.
وقتی دیدگاهی ثبت میکنید تا زمان تأیید شدن در سایت منتشر نمیشه و اگه ip و سیستمتون عوض بشه در صفحه نمیبینیدش
سلام استاد تشکر بابت مطالب مفیدتون
یک اسکریپت شبکه اجتماعی دارم کاربر سایت میتونه متن و تصویر و ویدئو پست کنه
اگر بخوام فایل موزیک رو هم پشتیبانی کنه و کاربر بتونه در پست ها اهنگ هم ارسال کنه باید چه کدهایی را بهش اضافه کنم ؟
سلام
بستگی به کدتون داره! احتمالاً یه جایی داره بررسی میکنه که فرمت فایل آپلودی مثلا عکس و ویدئو باشه. باید این رو ویرایش کنید.
اگه اسکریپتتون بخش مدیریت هم داره، ممکنه توی تنظیماتش جایی برای این مورد درنظر گرفته باشن.
بسیار عالی و کاربردی . ممنونم. برقرار و پاینده باشید
سلام خیلی عالی بود و از شما متشکرم برای این مطلب مفید و کاربردی.
دستت طلا
خیلی عالی بود دمت گرم
من چند روزی بود که درگیر این اپلود فایل بودم تا با خواندن مطلب شما مشکلم حل شد
خوشحالیم که این آموزش براتون کاربردی بوده سپهر عزیز. موفق باشید.
سلام
مطلبتون خیلی عالی بود
اما یه نکته؛
من تمام این کار هارو انجام دادم ولی با این ارور موجه شدم:
کد خط چهار این هست:
سلام محمدعلی عزیز
ویژگی name تگ input داخل فرم که برای فایلها گذاشتی برابر shot هست؟
یا اسم فیلد اشتباهه یا فرم مشکلی داره که فایلی به سرور ارسال نمیکنه!
سلام بله مشکل از فرم بود!
توی تگ فرم enctype رو ننوشته بودم!
ممنون از پاسخگوییتون…
سلام , خسته نباشید ؛ ممنون میشم اگه ممکن فایل زیپ شده ی این قسمت اپلود فایل رو در سایت بارگزاری کنید ؛ تشکر
سلام علیرضای عزیز
چون آموزش به صورت پروژهای نیست، فعلاً کد جامعی براش نداریم. میتونید به کمک فرم و کد قسمت «ذخیره فایل» فایل رو ذخیره کنید.
ممنون بابت پیشنهادت. در اولین فرصت یک کد کامل به آموزش اضافه میکنیم.