برنامه نویسی ASP.NET با دلفی قسمت نهم
فصل نهم
ارسال فایل به وب سرور توسط ASP.NET
ارسال فایل توسط مرور گر از سمت کاربر به سوی وب سرور
اکثر برنامه های ASP.NET و سایتهای مختلف به کاربران اجازه می دهند که فایلهایی را از کامپیوتر خود به وب سرور ارسال کنند. نمونه های این کاربرد را می توانید در سایتهای مدیریت محتوا مشاهده کنید . مثال BDswebExample نیز یک گزینه برای ارسال تصویر محصول به منظور ضمیمه شدن در لیست کالا در اختیار شما می گذارد .
HTMLInputFile:
ASP.NET به برنامه نویسان اجازه می دهد تا به سادگی امکان ارسال فایل را به برنامه های خود اضافه کنند . در سمت سرور گزینه ای که ASP.NET برای اینکار ارائه می کند HtmlInputFile می باشد و وظیفه مدیریت ارسال فایل را بر عهده دارد. برای ایجاد و استفاده از این گزینه تنها چند خط کد نویسی لازم است .
HtmlInputFile گزینه برنامه نویسی < input type=file > را فعال می کند از فصل قبل به خاطر دارید که این گزینه را چگونه از پالت ابزار انتخاب کرده و به صفحه اضافه کنید .
تنظیم صفحه برای ارسال فایل:
برای این کار باید مراحل ذیل صورت گیرد
1- زمانیکه روی صفحه طراحی هستید جزء HTML file up load را به صفحه خود اضافه کنید .
2- حال به صفحه کد aspx بروید و صفت runat = “server” را به
اضافه کنید تا امکان استفاده از این جزء در صفحه کد پنهان را داشته باشید .
3- با استفاده از ID یک نام مانند FileUpload به شی تشخیص دهید متن شی باید مانند این باشد:
4- حال محیط ویرایش را که فعال نموده و تعریف کنترل را به قسمت
"strict-protected" اضافه کنید مانند:
FileUpload : System.Web.UI.HtmlControls.HtmlInputFile;
5- و در آخر بسیار مهم است که تگ فرم شامل صفت
enctype="Multipart/Form-Data"
باشد. دقت کنید که اگر بخواهید صفحه خود را به شکل پویا بسازید باید encoding مناسب را از طریق برنامه نویسی اعمال کنید.
صفحه ای که در نهایت از این کد حاصل می شود ساده و شامل یک تگ ورود اطلاعات بوده، نوع فایل آن هم تعیین شده است. این تگ HTML دارای کادر ورود اطلاعات و دکمه Browse در کنار آن می باشد. زمانیکه که کاربر دکمه Browse را فشار می دهد کادر انتخاب فایل نمایش داده شده و امکان انتخاب فایل را به کار بر خواهد داد.
انتخاب (کاربر) ، دریافت و ذخیره فایل (سرور) ارسال شده:
کار عملی ذخیره معمولاً در متد اجرایی رویداد نوشته می شود (مثلاً در اجرای متد کلیک دکمه ) پس لازم است یک دکمه به فرم خود اضافه کنید تا بتواند نیاز شما را تأمین کند .
تذکر 1 :
ما باز هم کنترل های وب ASP.NET را بررسی خواهیم کرد. فقط در اینجا اشاره می کنیم که یک کلید وب تقریباً شبیه یک کلید عادی عمل می کند.
تذکر 2 :
در این کار دکمه HTML Button را بر ندارید و در عوض دکمه Button ازWeb Control را استفاده کنید .
صفحه طراحی را فعال کرده دکمه را از پالت ابزار انتخاب کنید و روی فرم قرار داده و نام آن را"UploadButton" بگذارید. متن نمایشی آن را به "Upload" تغییر دهید و با کلیک مضاعف روی دکمه یک تابع برای نوشتن دستورات خود ایجاد کنید. این کار سبب می شود که ساختار مناسب کد نویسی ایجاد و فعال شود. به این ترتیب می توانید دستورات خود را نوشته و این دستورات توسط کاربر در زمان کلیک روی دکمه اجرا می شود . نمونه زیر چگونگی ارسال فایل و کدهای مربوط به آن را نشان می دهد . زمانیکه کاربر دکمه ارسال را فشار می دهد یک کادر پیام نمایش داده شده و همزمان کار ارسال فایل ادامه پیدا می کند.
uses System.IO, ...
...
TWebForm1 = class(System.Web.UI.Page)
...
strict protected
FileUpload:System.Web.UI.HtmlControls.HtmlInputFile;
UploadButton:System.Web.UI.WebControls.Button;
...
procedure TWebForm2.UploadButton_Click
(sender: System.Object; e: System.EventArgs);
const
ServerSavePath = 'c:\MySite\Upload';
var
ClientFileName : string;
ServerFileName : string;
UploadOK : boolean;
begin
//make sure the client selected an existing file
if (not Assigned(FileUpload.PostedFile)) OR
(FileUpload.PostedFile.FileName.Length = 0) OR
(FileUpload.PostedFile.ContentLength = 0) then
begin
Dialogs.ShowMessage(
Self,
'No file selected to upload!',
'Warning',
TDlgType.mtWarning,
200);
Exit;
end;
(*save the file to the server*)
ClientFileName :=
Path.GetFileName
(FileUpload.PostedFile.FileName);
ServerFileName := // or GetUniqueFileName(...)
Path.Combine
(ServerSavePath, ClientFileName);
UploadOK := True;
try
FileUpload.PostedFile.SaveAs(ServerFileName);
except on Ex:Exception do
begin
UploadOK := False;
Dialogs.ShowMessage(
Self,
'An error occured while saving
the file to the server!' + #13#10 +
Ex.ToString,
'Error',
TDlgType.mtError,
0);
end;
end;
if UploadOK then
Dialogs.ShowMessage(
Self,
'File successfully uploaded
to the web server!',
'Upload',
TDlgType.mtInformation,
200);
end;
کنترل HtmlInputFile هیچ راهی برای انجام پست بک در خود ندارد و همچنین راهی برای ذخیره فایل در سرور هم ندارد . برای اینکه بتوان فایل را در سرور ذخیره کرد ما از خاصیت فایل ارسال شده PostedFile استفاده کرده ایم کنترل posted file در واقع یک شی HttpPostedFile بوده که خواص و روشهایی را برای به دست آوردن اطلاعات از یک فایل و خواندن و ذخیره آن به ما می دهد . در کل همه کدهای این قسمت چهار کار ساده را انجام می دهند .
? اولاً باید اطمینان پیدا کنیم کاربر فایلی را برای ارسال انتخاب کرده است این کار با بررسی مقدار قرار گرفته در عبارت صورت می گیرد:
FileUpload.PostedFile.FileName.Length = 0
? دوماً ما باید نام فایلی که قرار است ارسال شود را استخراج کنیم این کار هم با فرا خوانی متدPath.GetFileName صورت می گیرد که نوعی متد ثابت کلاس مسیر path بوده از فضای نام System.IO گرفته میشود.
? سوماً باید نام فایلی برای ذخیره روی سرور ایجاد کنیم . در اینجا برای تعیین مسیر از متد ServerFileName استفاده کرده ایم . روی سرور، فایل به همان نامی که کاربر ارسال کرده ذخیره می شود و تنها مسیر آن متفاوت است بنا براین از متد ترکیب مسیر با نام فایل استفاده می کنیم تا مطمئن باشیم که مسیر معتبر است .
? و در نهایت از متد SaveAs از کلاس HttpPostedFile برای ذخیره نهایی فایل روی سرور استفاده کرده ایم . همچنین دقت کنید که از یک بلوک خطا یابی برای ایجاد یک محیط نمایش خطا مانند معمول و در طول ارسال فایل استفاده کرده ایم . در صورتیکه از کادرهای محاوره منودیالوگ (MonoDialogs ) استفاده نمی کردیم باید از یک بر چسب برای نشان دادن پیام های خطا و غیره در طول ارسال فایل استفاده کنیم .
HttpPostedFile
همچنانکه مشاهده می کنید کار اصلی توسط کلاس HttpPostedFile صورت گرفته است. پس از آنکه کاربر فایلی را انتخاب کرده باشد شی HttpPostedFile مقداری معتبر پیدا می کند . این متد دارای خواص جالبی است که آنها را بررسی می کنیم:
FileName :
این خاصیت نام کامل فایل بر روی سیستم کار بر را ارائه می کند:
c:\ClientFolder\UserPicture.gif
ContentType :
نوع فایل ارسال را مشخص می کند. مثل : "image/gif"
InputStream :
نوعی اشاره گر به فایل ارسال شده System.IO.Stream میباشد . برای نمونه شما می توانید از خاصیت ContentLength برای تشخیص حجم فایل و در نتیجه اجتناب از دریافت فایلهای بزرگتر از 512 بهره ببرید :
with FileUpload.PostedFile
if ContentLength > 1024 * 512 then
//Exit the proc and notify the user that only
//files up to 512 Kb can be uploaded.
کجاها اشکال رخ می دهد ؟
1- خاصیت Enctype فرم HtmlForm در این کنترل خاص باید حتماً "multipart/form-data" قرار داده شده تا وظیفه خود را درست انجام دهد .
2- در زمان ذخیره فایل باید مسیر را به طور کامل در متد مربوطه تعیین کنید در غیر این صورت ASP.NET سعی خواهد کرد تا فایل را در مسیر
systemroot\system32\inetsrv ذخیره کند .
3- اضافه بر این ، اگر با خطای " دسترسی غیر مجاز " ("access denied" ) مواجه شدید باید اطمینان پیدا کنید نوع دسترسی میزبان یا اشخاص مجاز روی سرور با اجازه نوشتن (write) باشد. برای اصلاح این حالت روی پوشه مورد نظر راست کلیک کرده و گزینه Sharing and Security را انتخاب نموده و سپس به سراغ سر برگ Security بروید .
4- در صورتی که در مسیر ذخیره سرور فایلی با همین نام وجود داشته باشد دستورات فوق روی آن فایل خواهد نوشت . پس شاید بخواهید موضوع را تشخیص داده و نام دیگری را برای فایل انتخاب کنید . در اینجا تابعی که برای اینکار مفید است را ارائه می کنیم:
function GetUniqueFileName
(ServerSavePath, fileName:string):string;
begin
while Path.FileExists(Path.Combine( ServerFolder,fileName)) do
fileName := '_' + fileName;
Result := Path.Combine(ServerFolder,fileName);
end;
این تابع با افزودن "ـ" به هر تعداد که نیاز باشد به اسم فایل قبلی کار خود را انجام می دهد . برای مثال اگر نام فایل شما "myfile.zip" باشد و همین نام روی سرور وجود داشته باشد نام فایل شما به "_myfile.zip" تغییر داده می شود، مثل:
"c:\MySite\Upload\_myfile.zip"
روش استفاده از تابع فوق در برنامه نیز چنین است :
...
ServerFileName :=
GetUniqueFileName(
ServerSavePath,
ClientFileName);
...
اگر نخواهید از روش کد گذاری شده برای مسیر ذخیره فایل روی سرور استفاده کنید و به دنبال آن باشید که فایل ها را در مسیر خاصی از سایت ذخیره کنید، باید از متد MapPath از کلاس HTTPServerUtility استفاده کنید روش کار به این صورت می باشد: ServerSavePath := Server.MapPath('/Upload')
این تابع مسیرفیزیکی ذخیره را با توجه به مسیر وب سایت مشخص می کند یعنی اگر مسیر ذخیره سایت شما
'c:\InetPub\WWWRoot\MyWebApplication'
باشد مسیری که توسط دستور Server.MapPath('/Upload') ارجاء داده می شود به شکل:
'c:\InetPub\WWWRoot\MyWebApplication\Upload' خواهد بود.
کل کار را انجام دادیم
حال کاربران شما می توانند فایلهای خود را برایتان ارسال کنند . البته اگر بخواهید به کاربران خود اجازه بدهید تا فایلی را از روی سایت شما دریافت کنند باید روش آن را به نیز دنبال کنید.