فرایند آپلود فایل در وب
قبل از پرداختن به ادامه این آموزش، لازم است برای داشتن درک صحیحی از فرایند آپلود فایل در وب، به طور مختصر به آن اشاره ای داشته باشیم.
آنچه که مسلم است، دسترسی به فایل های کاربران در وب از لحاظ امنیتی غیر استاندارد و ممنوع است، به این لحاظ از طریق کدهای html و عناصر موجود در تگ form، این قابلیت وجود دارد که حق انتخاب (یا در واقع حق آپلود فایل) در دست کاربر باشد تا اگر خود او تمایل داشت، فایل های مورد نظرش را انتخاب و تحت پروتکل های انتقال داده در وب، به سرور ارسال نماید، در سرور این فایل ها توسط برنامه نویسی سمت سرور مانند زبان php یا موارد مشابه، مدیریت می شوند و اگر همه چیز درست باشد، فایل بر روی حافظه سخت افزاری یا به عبارتی هارددیسک سرور، ذخیره شده و قابل استفاده است.
چگونه یک فایل را با آژاکس آپلود کنیم؟
اگرچه فناوری آژاکس از بسیاری جنبه ها پیشرفت کرده است و می توان به کمک آن مقادیر موجود در فرم های html را بدون رفرش صفحه به سرور ارسال کرد، اما واقعیت این است که در مورد ارسال فایل، هنوز به استاندارهای لازم نرسیده است، به این دلیل است که برخی توابع تعریف شده آن، برای برخی مرورگرها قابل فهم و پشتیبانی نیست و نمی توان چندان بر آن متکی بود، از اینرو، کنسرسیوم جهانی وب (W3C) در حال تکمیل کردن نسل جدیدی از XMLHttpRequest با نام XMLHttpRequest2 است تا در این نسخه استاندار انتقال فایل نیز در بستر آژاکس به درستی تعریف شود، به هر صورت برای کاربران، گزینه های جایگزین دیگری وجود دارد، از جمله استفاده از کتابخانه های جاوا اسکریپتی نظیر جی کئوری (jQuery) و موتولز (Mootools)، که با جلوه ها و محیط کاربری خیلی زیبایی می توانند فایل ها را آپلود کنند (البته مشکل همیشگی این نوع کتابخانه ها مخصوصا برای کاربران با سرعت و کیفیت پائین اینترنت، حجم آنها است).
در این آموزش ما از روشی شبیه سازی شده بر اساس فرایند آژاکسی ولی مبتنی بر جاوا اسکریپت و تکنیک iframe استفاده خواهیم کرد.
کد html برای آپلود فایل
همانطور که گفتیم قبل از هرچیز برای آپلود فایل در وب، به فرم مبتنی بر کدهای html نیاز داریم، بدین منظور فرم زیر و سایر تنظیمات html را ایجاد می کنیم.
<form action="php-ajax-upload.php" method="post" enctype="multipart/form-data" target="upload-target" onsubmit="upload_start();">
<label for="user-file"></label>
<input type="file" id="user-file" name="user-file" />
<input type="submit" value="آپلود فایل" />
</form>
<div id="upload-process"><img src="loading.gif" height="16" width="16" alt="loading" /> در حال پردازش...</div>
<div id="upload-form"></div>
<iframe id="upload-target" name="upload-target" class="frame"></iframe>
توضیح:
- در قسمت action فرم، آدرس فایل php مقصد را که فایل های آپلود شده ما را پردازش و مدیریت خواهد کرد، وارد می کنیم.
- در قسمت متد ارسال فایل، از متد post استفاده خواهیم کرد.
- بخش مربوط به enctype و مقادیر multipart/form-data این امکان را به مرورگر خواهد داد تا فایل را به صورتی باینری و تکه تکه به سرور انتقال دهد، در حالت معمول و به طور پیش فرض، مرورگر از application/x-www-form-urlencoded استفاده می کند که برای انتقال فایل مناسب نیست.
- قسمت مربوط به target به جهت استفاده از تکنیک iframe قرار داده شده است که مقادیر آن در واقع آی دی iframe است، گفتیم که در حال حاضر آژاکس به خودی خود نمی تواند فایل ها را به طور کامل و در تمام مرورگرها آپلود کند و باید از فریم ورک ها (Ajax Frameworks) یا روش های شبیه سازی شده استفاده کنیم.
- قسمت مربوط به onsubmit و مقادیر آن مربوط به فراخوانی تابع جاوا اسکریپتی است که هنگام ارسال فرم، اجرا می شود و وظیفه مدیریت نمایش پیام های در حال پردازش و پاسخ سرور را دارد.
- برای ارسال فایل باید از input و نوع file بدین منظور استفاده کنیم، ذکر این نکته لازم است که مقادیر دکمه انتخاب فایل (choose file)، به صورت پیش فرض توسط مرورگرها پردازش می شود و برای تغییر آن باید از تکنیک css و جاوا اسکریپت استفاده کرد.
- نهایتا نیز با یک دکمه از نوع submit فرم را ارسال می کنیم، نکته مهم در اینجا این است که نوع دکمه ارسال فایل باید حتما submit باشد، چرا که ما پیش تر برای اجرای تابع جاوا اسکریپتی خود از رویداد onsubmit استفاده کرده ایم.
- بلاک های div که در پائین فرم ایجاد کرده ایم، برای مدیریت نمایش پیام در حال پردازش و نمایش پیغام خطا یا موفقیت آمیز بودن آپلود است.
- iframe را نیز برای دریافت پیام سرور، بعد از آپلود فایل، ایجاد کرده ایم.
کد css و جاوا اسکریپت
برای اینکه برنامه ما به درستی کار کند، باید تنظیمات و کنترل کامل تری روی آن اعمال کنیم، بدین منظور از کدهای css و جاوا اسکریپت (Javascript) به شکل زیر استفاده می کنیم.
<style type="text/css">
body{
font-family:Tahoma, Geneva, sans-serif;
font-size:12px;
direction:rtl;
}
a{
text-decoration:none;
color:#06C;
}
a:hover{
color:#666;
}
.ok {
display:block;
padding:4px;
border:0px #666 solid;
color:#090;
width:300px;
}
.error {
display:block;
padding:4px;
border:0px #666 solid;
color:#C00;
width:300px;
}
#upload-process{
z-index:1000;
visibility:hidden;
}
.frame{
width:300px;
height:100px;
border:0px;
}
</style>
<script type="text/javascript">
//<![CDATA[
function upload_start(){
document.getElementById(upload-process).style.visibility = visible;
return true;
}
function upload_end(check_upload){
var server_response = ;
if (check_upload == 1){
server_response = <span class="ok">فایل با موفقیت آپلود شد!</span>;
}
else {
server_response = <span class="error">انتقال فایل به سرور انجام نشد!</span>;
}
document.getElementById(upload-process).style.visibility = hidden;
document.getElementById(upload-form).innerHTML = server_response;
return true;
}
//]]>
</script>
توضیح:
- فایل css ما، تنظیمات مربوط به ظاهر عناصر را مدیریت خواهد کرد و با دقت در مقادیر کلاس ها و آی دی، به راحتی می توانید از خواص آنها مطلع شوید.
- کد جاوا اسکریپت بالا، دارای دو تابع ساده است، تابع اول با نام upload_start با ارسال فرم، شروع می شود و استایل عنصر با آی دی upload-process را به حالت مرئی یا visible تبدیل می کند، در تابع دوم upload_end، یک عدد که از کد php دریافت می شود را بررسی کرده و متناسب با آن پیام و اطلاعاتی به کاربر نشان داده می شود، در اینجا از innerHTML برای نمایش اطلاعات استفاده کرده ایم.
کد php برای پردازش فایل آپلود شده
پس از اینکه کاربر فایل خود را ارسال می کند، در سمت سرور، باید کدی داشته باشیم که بتواند فایل آپلود شده را مدیریت کند، در php متغیر ازپیش تعریف شده یا (Predefined Variable) با نام FILES وجود دارد که بدین منظور مورد استفاده قرار می گیرد، قبل از توضیح موارد، اجازه دهید فایل را با هم ملاحظه کنیم.
<?php
//تعیین فرمت یا اندازه مجاز و سایر پارامترها
if ($_FILES["user-file"]["type"] == "image/jpeg" && $_FILES["user-file"]["size"] < 1000000) {
//بررسی سایر خطاهای سرور
if ($_FILES["user-file"]["error"] > 0){
echo "<div class="server">خطا: " . $_FILES["user-file"]["error"] . "</div><br />";
$check_result = 0;
}
//بررسی وجود یا عدم وجود فایل با نام مشابه در سرور
else{
if (file_exists("user-upload/" . $_FILES["user-file"]["name"])){
echo "<div class="server">این فایل در حال حاضر وجود دارد! <br /><br />".$_FILES["user-file"]["name"]. "</div><br />";
$check_result = 0;
}
//انتقال و ذخیره فایل در سرور
else{
move_uploaded_file($_FILES["user-file"]["tmp_name"],"user-upload/" . $_FILES["user-file"]["name"]);
echo "فایل: " . $_FILES["user-file"]["name"] . "<br />";
echo "نوع: " . $_FILES["user-file"]["type"] . "<br />";
echo "اندازه: " . ($_FILES["user-file"]["size"] / 1024) . " Kb<br />";
echo "دایرکتوری: " . "user-upload/" . $_FILES["user-file"]["name"]. "<br />";
$check_result = 1;
}
}
}
//خطای تعیین فرمت یا اندازه مجاز و سایر پارامترها
else{
if($_FILES["user-file"]["size"] > 1000000){
echo "<div class="server">حجم فایل خیلی زیاد است!</div>";
}
else{
echo "<div class="server">فرمت فایل مجاز نیست!</div>";
}
$check_result = 0;
}
?>
توضیح:
- همانطور که گفتیم، برای دریافت یک فایل آپلود شده در php از متغیر از پیش تعریف شده FILES استفاده می کنیم، مقادیر اول این متغیر در واقع نام فیلدی است که فایل از آن ارسال می شود، مقادیر دوم تنظیمات مروبط به فایل آپلود شده است.
- تنظیمات فایل آپلود شده می تواند شامل موارد زیر باشد:
<?php
//نام فایل آپلود شده
$_FILES[user-file][name];
//نوع فایل مانند image/jpeg
$_FILES[user-file][type];
//حجم فایل به بایت
$_FILES[user-file][size];
//نام موقت فایل در سرور
$_FILES[user-file][tmp_name];
//شماره خطای برگردانده شده توسط سرور
$_FILES[user-file][error];
?>
- خطاهای مربوط به کار با فایل، اعدادی از 1 تا 8 هستند، اگر همه چیز درست باشد، عدد صفر برگردانده می شود، در زیر به طور مختصر به این خطاها اشاره می کنیم:
UPLOAD_ERR_OK: عدد صفر برگردانده می شود و این به معنی عدم خطا است.
UPLOAD_ERR_INI_SIZE: عدد 1 برگردانده می شود، فایل آپلود شده از حداکثر حجم تنظیم شده در php.ini بیشتر است.
UPLOAD_ERR_FORM_SIZE: عدد 2 برگردانده می شود، فایل آپلود شده از حداکثر حجم تنظیم شده در فرم html بیشتر است.
UPLOAD_ERR_PARTIAL: عدد 3 برگردانده می شود، فایل به صورت ناقص آپلود شده است.
UPLOAD_ERR_NO_FILE: عدد 4 برگردانده می شود، هیچ فایلی آپلود نشد.
UPLOAD_ERR_EMPTY: عدد 5 برگردانده می شود، فایل آپلود شده صفر بایت است یا فیلد خالی است.
UPLOAD_ERR_NO_TMP_DIR: عدد 6 برگردانده می شود (تنها در نسخه 4.3.10 و بالاتر)، مفسر php نمی تواند پوشه tmp را پیدا کند.
UPLOAD_ERR_CANT_WRITE: عدد 7 برگردانده می شود (تنها در نسخه 5.1.0 و بالاتر)، مفسر php نمی تواند فایل را ذخیره کند.
UPLOAD_ERR_EXTENSION: عدد 8 برگردانده می شود (تنها در نسخه 5.2.0 و بالاتر)، یکی از الحاقات php، مانع آپلود فایل شده است، استفاده از ()phpinfo ممکن است به رفع مشکل کمک کند.
- تابع file_exists بررسی می کند که آیا فایل ارسال شده از قبل در دایرکتوری مورد نظر وجود دارد یا خیر.
- اگر همه چیز درست باشد، نهایتا php با تابع move_uploaded_file، فایل را در دایرکتوری مورد نظر ذخیره می کند.
دانلود کد آپلود فایل با php به شیوه آژاکسی
در زیر کدهای بالا را به اضافه تنظیماتی کامل تر، در یک بسته جهت دانلود قرار داده ایم، پس از دریافت فایل کافی است آن را روی لوکال هاست اجرا کنید.
دانلود کد آپلود فایل با php به شیوه آژاکسی - حجم: کمتر از 5 کیلوبایت
نکته: این برنامه صرفا جنبه آموزشی داشته و استفاده از آن بدون تسلط بر php و توابع مربوط به فایل، توصیه نمی شود.