محتویات سایت
        برچسب های محبوب 








 
   ایجاد دانلود هوشمندانه در نرم افزارهای تحت وب
  دانلود فایل در نرم افزار های تحت وب به سادگی ایجاد یک لینک توسط HTML می باشد. که کاربران سایت با کلیک کردن روی لینک مورد نظر می توانند نسبت به دانلود اقدام نمایند. ولی در شرایط گوناگون این بهترین راه حل نمی باشد
   ASP.NET
   ۹۴۷۷
    سورس کد
   مرتضی صحراگرد
   ۱۳۸۵/۹/۵
نسخه قابل چاپ نسخه قابل چاپ

ايجاد دانلود هوشمندانه در نرم افزارهاي تحت وب :


دانلود فايل در نرم افزار هاي تحت وب به سادگي ايجاد يک لينک توسط HTML مي باشد. که کاربران سايت با کليک کردن روي لينک مورد نظر مي توانند نسبت به دانلود اقدام نمايند. ولي در شرايط گوناگون اين بهترين راه حل نمي باشد. به عنوان مثال :
هنگامي که فايل دانلودي بسيار حجيم باشد.
هنگامي که مايل نيستيد کاربران محل دقيق فيزيکي فايل روي ديسک سخت را ببينند.
هنگامي که براي دانلود فايل شرايط بخصوصي را در نظر گرفته باشيد مثلا قبل از اينکه فايل را بتوانند دانلود کنند بايد در سايت ثبت نام کرده باشند.
هنگامي که مي خواهيد اطمينان داشته باشيد که کاربران فقط از درون سايت شما بتوانند فايل را دانلود کنند و ديگران نتوانند با دادن لينک مستقيم از خارج از وب سايت شما به فايل دسترسي پيدا کرده و از پهناي باند شما استفاده نمايند.
و دلايل بسيار ديگر.
در اين شرايط شما بايد امکاني داشته باشيد که قبل از داونلود بتوانيد وضعيت کاربر را کنترل نماييد .
در اين مقاله براي شما راه حل هايي را براي داشتن دانلود سريعتر و خالي از اشکال  ارائه خواهم داد.
راه حل هاي زير پيشنهاد مي شود.
استفاده از متد Response.WriteFile
استريم کردن فايل با استفاده از متد Response.BinaryWrite.
استفاده از Response.TransmitFile
استفاده از يک فيلتر ISAPI
نوشتن يک کنترل Browser سفارشي


راه حل اول :


ساده ترين راه حل استفاده از متد  Response.WriteFile مي باشد . همانطور که در زير مشاهده  مي کنيد اين قطعه کد مسير فايل را از نوار آدرس مرورگر به صورت يک پارامتر گرفته و دانلود را ايجاد مي کند.


if (Request.QueryString("FileName"))

{

Response.Clear();

Response.WriteFile(Request.QueryString("FileName"));

Response.End();

}

هنگامي که اين قطعه کد اجرا مي شود ، کارگزارIIS يعني (aspnet_wp.exe در IIS 5.0  و يا w3wp.exe در IIS 6.0 ) متد Response.Write را فراخواني مي کند و کارگزار فرايند ASP.NET يعني (ASP.NET worker process) ارسال ديتا به کارگزار IIS را شروع مي کند.
از زماني که ديتا از کارگزار فرآيند ASP.NET به کارگزار IIS شروع شد ، فايل شروع به بافر شدن در حافظه مي کند . در بسياري از موارد اين موضوع نگران کننده نمي باشد ولي براي فايلهاي حجيم اين بهترين راه حل نمي باشد .
فرض کنيد شما يک فايل ويدئويي با حجم 300 مگا بايتي براي دانلود گذاشته باشيد ،  در اين صورت قبل از اينکه کاربر شروع به دانلود فايل نمايد ، اين فايل بايد در حافظه سرور بافر شود . و همچنين تصور کنيد که تعدادي از کاربران به طور همزمان شروع به دانلود فايل نمايند. در اين هنگام حافظه عظيمي از سروري اشغال مي شود که معمولا چنين اجازه اي از سوي سرور به سايت شما داده نمي شود و در با خطاي RunTime Error روبرو شده و يا گاهي اوقات با خطاي زير :


Server Application Unavailable

The Web application you are
attempting to access on this Web
server is currently unavailable.
Please hit the "Refresh" button in your Web
browser to retry your request.

Administrator Note: An error message detailing
the cause of this specific request failure can be
found in the system event log of the Web server.
Please review this log entry to discover what
caused this error to occur.

طبق آزمايش تجربي که بنده روي يک سرور که IIS 5.0 رو آن نصب شده و داراي 2 گيگابايت حافظه بود انجام دادم ، هنگامي که حجم فايل دانلودي حدود 200 مگابايت شد ، در دانلود خطا ايجاد شد.
در حاليکه در محيط عملي که چندين کاربر به طور همزمان شروع به دانلود مي نمايند اين مشکل بيشتر نمايان شده و در بيشتر سرور ها اين خطا ايجاد مي شود.
دانلود کردن فايلهاي حجيم در قطعات کوچکتر :
يک راه حل براي مشکل بالا تقسيم کردن فايلها به قطعات کوچکتر و قابل مديريت مي باشد . در قطعه کد زير اين مسئله را مشاهده مي کنيم.
در اين کد ما فايل را به قطعات 10000 بايتي تقسيم کرده (در يک حلقه While) و اين قطعه را براي مرورگر ارسال مي کنيم و سپس قطعه بعدي خوانده مي شود. در نتيجه در داونلود مقدار قابل توجهي از حافظه سرور اشغال نمي شود.
اين روش را بنده براي يک فايل با حجم 1.6 گيگابايت آزمايش نمودم و نتيجه دانلودي سريع و بدون هيچ مشکلي بود.
دقت داشته باشيد که خود IIS دانلود فايلهاي با حجم بيشتر از 2 گيگابايت را حمايت نمي کند و اگر قصد داريد فايلهاي با حجم بيشتر از 2 گيگابايت را براي دانلود بگذاريد بايد از FTP و يا يک کنترل واسطه خارجي (third-party) ويا Microsoft Background Intelligent Transfer Service  و يا راه حلهاي سفارشي مانند استريم کردن ديتا بين سوکتها با يک کنترل سفارشي Browser-Hosted مي باشد.
دقت کنيد که ما اينجا با متد Response.IsClientConnected چک مي کنيم که کاربر هنوز متصل (Connect) است يا خير.


protected void Page_Load(object sender, EventArgs e)

{

string dlDir = "downloadfiles/";

string strFileName = Request.QueryString("FileName");

string path = Server.MapPath(dlDir + Request.QueryString("FileName"));

System.IO.FileInfo toDownload = new System.IO.FileInfo(path);

if (IsSafeFileName(strFileName) && toDownload.Exists)

{

const long ChunkSize = 10000;

byte[] buffer = new byte[ChunkSize];

Response.Clear();

using (FileStream iStream = File.OpenRead(path))

{

long dataLengthToRead = iStream.Length;

Response.ContentType = "application/octet-stream";

Response.AddHeader("Content-Disposition", "attachment; filename="

+ toDownload.Name);

while (dataLengthToRead > 0 && Response.IsClientConnected)

{

int lengthRead = iStream.Read(buffer, 0, ChunkSize);

Response.OutputStream.Write(buffer, 0, lengthRead);

Response.Flush();

dataLengthToRead = dataLengthToRead - lengthRead;

}

}

Response.Close();

}

}

راه حل بهتر
تيم توسعه دهنده ASP.NET2  براي رفع مشکلات مطرح شده راه حلي ايجاد نموده اند تا فايل به مرورگر ارسال شود ، بدون اينکه د رحافظه سرور بافر شود . و آن چيزي نيست جز  Response.TransmitFile ، که هم اکنون در ASP.NET2 موجود مي باشد. در قطعه کد زير از اين روش استفاده شده است.


protected void Page_Load(object sender, EventArgs e)

{

string dlDir = "downloadfiles/";

string strFileName = Request.QueryString("FileName");

string path = Server.MapPath(dlDir + Request.QueryString("FileName"));

System.IO.FileInfo toDownload = new System.IO.FileInfo(path);

if (IsSafeFileName(strFileName) && toDownload.Exists)

{

Response.Clear();

switch (System.IO.Path.GetExtension(strFileName))

{

case ".zip":

Response.ContentType = "application/x-zip-compressed";

Response.AddHeader("Content-Disposition", "attachment;filename=NEWDL_" + toDownload.Name);

Response.TransmitFile(path);

break;

default:

// File Extension not supported.

}

Response.End();

}

}

منبع : MSDN Magazine > September 2006