PDA

View Full Version : دانلود فایل با قابلیت Resume



mahdi_negahi
یک شنبه 21 بهمن 1386, 15:18 عصر
سلام

آیا کسی راهی برای این مسئله می داند؟

SalarSoft
یک شنبه 21 بهمن 1386, 16:36 عصر
خیلی وقته حل شده

mahdi_negahi
یک شنبه 21 بهمن 1386, 18:44 عصر
طرز استفادش را میگی سالار جان ؟

SalarSoft
دوشنبه 22 بهمن 1386, 07:45 صبح
این نمونه طرز استفاده رو نشون می ده.


DownloadFile("c:\\file.txt");


private void DownloadFile(string fileName)
{
try
{
byte[] downData;
int fileLen;

FileStream file = File.OpenRead(fileName);
try
{
fileLen = Convert.ToInt32(file.Length);
downData = new byte[fileLen];
file.Read(downData, 0, fileLen);
}
finally
{
if (file != null)
{
file.Close();
file.Dispose();
}
file = null;
}
string fileHeaderName = Path.GetFileName(fileName).Replace(' ', '-');

ResumableDownload downloader = new ResumableDownload();
downloader.ClearResponseData();

DownloadState downState = downloader.ProcessDownload(downData, fileHeaderName, fileHeaderName);
System.Diagnostics.Debug.WriteLine("\nDownloadState=" + downState.ToString());

downData = null;

if (downState == DownloadState.fsDownloadFinished)
{
// Do somthing
}
}
catch (System.Threading.ThreadAbortException)
{
// Nothing
}
}

mahdi_negahi
دوشنبه 22 بهمن 1386, 13:32 عصر
سالار جان دست شما درد نکنه

ولی یک مشکل ، این کار شما برای فایل 20 مگی خوبه چون فایل را درون پروسس ASP.NET لود میکند و رم سرور با این کار پر میشود
فایل های من 700 مگی هستند
شما از این استفاده کردید

objResponse.OutputStream.Write(bBuffer, 0, iLengthOfReadChunk);
ولی برای اینکه فایل درون رم سرور لود نشود بنا به تاپیک زیر

http://forums.asp.net/p/1125626/1839693.aspx#1839693
باید از

TransmitFile()
استفاده کنیم

شما نظرتون چیست ؟

SalarSoft
دوشنبه 22 بهمن 1386, 21:40 عصر
شما از این استفاده کردید
اگه به خط بعدی نگاه کنی نابع Flush استفاده شده. این تابع بافر جاری رو به کاربر ارسال می کنه.
و این مانع مشکلی که گفتی خواهد شد.


بنا به تاپیک زیر
TransmitFile ذاتا از resume پشتیانی نمی کنه.
در اون تکه کدی که نوشتن اگه بعد OutputStream.Write تابع Flush رو صدا می زد مشکل حل می شد.


با این حال این کلاس برای کار با فایل های بزرگ مشکل داره و مشکل چیزی نیست که تو گفتی.

مشکل ورودی تابع هست که از نوع byte و باید از نوع stream باشه.

فردا یه نگاهی می کنم تا این کلاس بر اساس Stream کار کنه و مشکل حل بشه.

mahdi_negahi
دوشنبه 22 بهمن 1386, 22:23 عصر
سالار جان در SP 1 .NET framework دو تا overload به این متد اضافه شده بنا به تاپیک زیر

http://support.microsoft.com/kb/927128

و بنا به تاپیک زیر این overload جدید resum ساپورت میکنه

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=277370

من دقیقا یک فایل 700MB گذاشتم و وای ی ی ی ی ی ی ی
با remote به سرورم وصل شدم دیدم سرور ترکیده end task کردمش

SalarSoft
سه شنبه 23 بهمن 1386, 17:01 عصر
من اطلاعی از این overload ها نداشتم.
بررسی می کنم.

با این حال همونطور که گفته بودم مشکل مربوط به خواندن فایل به باف در این کلاس بود که حلش کردم.

من این کلاس رو با فایل 70 MB تست کردم و یک مگ هم سربار نداشت.

این هم نمونه استفاده شده:


private DownloadState DoDownload(string fileName)
{
try
{

string fileHeaderName = Path.GetFileName(fileName).Replace(' ', '-');

ResumeDownload down = new ResumeDownload();
down.ClearResponseData();

DownloadState downState = down.ProcessDownload(fileName, fileHeaderName);
System.Diagnostics.Debug.WriteLine("\nDownloadState=" + downState.ToString());

if (downState == DownloadState.fsDownloadFinished)
{
// Do something here
}

return downState;
}
catch (ThreadAbortException)
{
// Nothing
}

مهدی کرامتی
سه شنبه 23 بهمن 1386, 17:37 عصر
سلام.

با تشکر،
من این پروسه رو برای فایلهای بزرگ تست کردم، خوب کار میکنه. اما بین 28 تا 38 درصد از پروسس CPU رو به ازای هر دانلود میگیره، همچنین خروجی اش رو با FlashGet تست کن، در بازه های زمانی بین 700 تا 1500 میلی ثانیه یکبار کانکشن اش ریست میشه (این رو با Casini که رو خود ویژوال استودیو 2005 هست تست کردم).

loveishere
سه شنبه 23 بهمن 1386, 17:49 عصر
دوست عزیز SalarSoft
ممنون از پیگیری شما،
اگر وقت دارید از متد TransmitFile همراه با overload های جدید هم استفاده کنید، اینطور که به نظر میرسه باید بازدهی بهتری داشته باشه

loveishere
سه شنبه 23 بهمن 1386, 20:24 عصر
من اطلاعی از این overload ها نداشتم.
بررسی می کنم.

با این حال همونطور که گفته بودم مشکل مربوط به خواندن فایل به باف در این کلاس بود که حلش کردم.

من این کلاس رو با فایل 70 MB تست کردم و یک مگ هم سربار نداشت.

این هم نمونه استفاده شده:


private DownloadState DoDownload(string fileName)
{
try
{

string fileHeaderName = Path.GetFileName(fileName).Replace(' ', '-');

ResumeDownload down = new ResumeDownload();
down.ClearResponseData();

DownloadState downState = down.ProcessDownload(fileName, fileHeaderName);
System.Diagnostics.Debug.WriteLine("\nDownloadState=" + downState.ToString());

if (downState == DownloadState.fsDownloadFinished)
{
// Do something here
}

return downState;
}
catch (ThreadAbortException)
{
// Nothing
}


SalarSoft جان
مطمئن هستید فایل درست رو آپلود کردید و یا روش استفاده اون رو درست نوشتید، من تست کردم ، ولی هیچ اتفاقی نمی افته ، فقط صفحه مجددا لود میشه، کلاس قبلی که گذاشته بودید بجز همان مشکل بافر مشکلی نداشت و خوب کار می کرد ولی این یکی اصلا جواب نمیده

arash1718
سه شنبه 23 بهمن 1386, 21:23 عصر
فرق کلاس HttpRequest که شما استفاده کردین با HttpWebRequest در System.Net چیه؟

loveishere
سه شنبه 23 بهمن 1386, 22:24 عصر
Salar جان ممنون
درستش کردم، مشکل server.mappath بود که استفاده نشده بود، جالب اینجا بود که هیچ پیغام خطایی نمی داد، ولی خب حل شد


سلام.

با تشکر،
من این پروسه رو برای فایلهای بزرگ تست کردم، خوب کار میکنه. اما بین 28 تا 38 درصد از پروسس CPU رو به ازای هر دانلود میگیره، همچنین خروجی اش رو با FlashGet تست کن، در بازه های زمانی بین 700 تا 1500 میلی ثانیه یکبار کانکشن اش ریست میشه (این رو با Casini که رو خود ویژوال استودیو 2005 هست تست کردم).

من هم روی لوکال و هم production server تست کردم، مشکل cpu نداشت و پردازش کاملا عادی بود ، کانکشن لاست یا ریست در دو تا از پارت های دانلود بود با Flash get تست کردم.
که البته من حدس میزنم بخاطر وضعیت فعلی اینترنت ایران است (قطعی فیبرهای نوری در دریای مدیترانه)، چون وقتی پینگ هم می کنیم زیاد کانکشن لاست و timeout دارد، البته الان یک فایل را از سایت مایکروسافت هم دانلود کردم که اون هم کانکشن لاست داشت.
اینطور که به نظر می رسه مشکل حل شده، ولی اگر Salar لطف کنند و باز هم برای اطمینان این کانکشن لاست رو چک کنند بد نیست و اگر وقت کردند با متد TransmitFile هم کلاس رو بازنویسی کنند خیلی عالی میشه

ممنون از همگی

loveishere
چهارشنبه 24 بهمن 1386, 07:55 صبح
سلام

دیشب، درحال دانلود یک فایل 200 مگابایتی بودم حدود 10 مگابایت اون دانلودشده بود و pause کرده بودم (با Dap ) ولی بعد از ادامه دانلود dap دانلود رو ریست کرد و از اول دانلود کردش، حالا نمی دونم دلیلش چی بود ارتباطی به اون ریست شدن کانکشن که DelphiAssistant بهش اشاره کردند داره یا نه،

البته این رو هم اضافه کنم که سیستم دانلود من نیاز به لاگین کردن کاربران داره، یعنی بعد از اینکه چک شد که آیا کاربر Authenticated هست یا خیر متد مربوط به دانلود فایل رو اجرا می کنه و اگر نبود کاربر رو به صفحه ورود می فرسته، حالا فرض کنید کاربر یک بار در سایت لاگین کرده که فایل رو دانلود کنه بدون مشکل شروع به دانلود فایل میکنه آیا بعد از بستن مرورگر و حتی sign out باز هم می تونه بدون مشکل دانلود رو ادامه بده ؟ (آیا برنامه های دانلود منیجر کوکی ها رو بصورت جداگانه ذخیر می کنند ؟)
این رو خودم دیشب تست کردم با یک کاربر بصورت موقت لاگین و شروع به دانلود فایل کردم ، sign out کردم و الان (بعد از گذشت حدود 11 ساعت) دوباره دانلود فایل رو ادامه دادم فایل راحت دانلود میشه (این خیلی خوبه ولی آیا مطمئن و safe هست، آیا میشه اطمینان داشت که بعدا سیستم دانلود رو ریست نکنه و از اول مجبور نشیم دانلود کنیم ؟ )

آپدیت شد : جواب سئوال خودم، اولین باره چنین چیزی می بینم، زمانیکه با دانلود منیجر فایل رو دانلود می کنم حتی اگر در سایت لاگین نکرده باشم، دانلود منیجر بصورت خودکار با یوزری که قبلا برای شروع دانلود لاگین کرده بود بصورت خودکار لاگین می کنه ، حتی من با یک یوز دیگر هم لاگین کردم ولی اطلاعات ذخیره شده در دانلود منیجر تغییر نکرد و باز هم با همان یور در حال دانلود فایل است، خیلی خوبه ولی آیا میشه به این اعتماد کرد آیا safe است ؟

SalarSoft
چهارشنبه 24 بهمن 1386, 10:53 صبح
اما بین 28 تا 38 درصد از پروسس CPU رو به ازای هر دانلود میگیره، همچنین خروجی اش رو با FlashGet تست کن، در بازه های زمانی بین 700 تا 1500 میلی ثانیه یکبار کانکشن اش ریست میشه
علت استفاده زیاد از CPU مربوط به ریست شدن کانکشن هست.
مشکل ریست شدن کانکشن در SP 1 حل شده و در نتیجه مشکلی با درصد بالای کار cpu نباید به وجود باید.


در SP 1 .NET framework دو تا overload به این متد اضافه شده بنا به تاپیک زیر
خیلی جالبه بدونید که ذاتا این overload ها قبلا (قبل از SP1) هم وجود داشتند و حالا فقط برای اونها تابع تعریف شده.

برای مثال اگر می خواهید که از متد TransmitFile بدون نصب SP1 استفاده کنید از تابع کع نوشتم استفاده کنید:


void CallHiddenTransmitFile(HttpResponse objResponse,string fileName, long offset, long size)
{
Type tempType = objResponse.GetType();
FieldInfo tempInfo = tempType.GetField("_httpWriter", BindingFlags.NonPublic | BindingFlags.Instance);
HttpWriter _httpWriter = (HttpWriter)tempInfo.GetValue(objResponse);

tempType=tempInfo.FieldType;
tempInfo = tempType.GetField("_buffers", BindingFlags.NonPublic | BindingFlags.Instance);
ArrayList _buffers=(ArrayList)tempInfo.GetValue(_httpWriter) ;

tempType = _httpWriter.GetType();
tempInfo = tempType.GetField("_responseBufferingOn", BindingFlags.NonPublic | BindingFlags.Instance);
bool responseBufferingOn=(bool)tempInfo.GetValue(_httpW riter);


Type classType = tempType.Assembly.GetType("System.Web.HttpFileResponseElement");
ConstructorInfo[] cinf = classType.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
object ret= cinf[2].Invoke(new object[]{fileName,offset,size,true,false,true});
_buffers.Add(ret);

if (!responseBufferingOn)
{
objResponse.Flush();
}
}


این تابع به عنوان overload در SP 1 عرضه شده که مسلما خیلی از سرور ها هنوز اون رو نصب نکردن پس می تونه برای استفاده یک گزینه خوب باشه.

SalarSoft
چهارشنبه 24 بهمن 1386, 11:15 صبح
این کلاس رو من با استفاده از overload جدید تابع transmitFile بازسازی کردم
تست شد و مشکل استفاده از CPU زیاد و یا ریست شدن کانکشن نداشت.

نکته: اگر .NET Framework SP1 رو نصب نکرده باشید با مشکلات مذبور مواجه خواهید شد.


برای سرورهایی که SP1 رو نصب کردن فایل ResumeDownload for SP1.zip رو دانلود کنید و برای سرورهایی که ندارن فایل ResumeDownload Not SP1.zip دانلود کنید.

تنها فرق این دو فایل در خط 332 هست که CallHiddenTransmitFile یا objResponse.TransmitFile فراخوانی شده.

نحوه استفاده فرق نکرده ولی دوباره می نویسم:

public static void DownloadFile(string fileName)
{
try
{
string fileHeaderName = System.IO.Path.GetFileName(fileName).Replace(' ', '-');
SalarSoft.Utility.ResumeDownload down = new SalarSoft.Utility.ResumeDownload();

// Start downloading
SalarSoft.Utility.DownloadState state = down.ProcessDownload(fileName, fileHeaderName);

if (state == SalarSoft.Utility.DownloadState.fsDownloadFinished )
{
// Your code
}
}
catch (System.Threading.ThreadAbortException)
{
// Nothing
}
}


* مدیر بخش یا سایت اگر امکانش هست این رو به عنوان اعلان بزنن شاید مشکل خیلی ها باشه.

loveishere
چهارشنبه 24 بهمن 1386, 11:25 صبح
خیلی ممنون ، لطف کردید
من نیاز به یک سیستم دانلود با بازدهی خوب و البته کاملا stable دارم ، نظر شما کدامیک است، متد قبلی یا این متد جدید TransmitFile ؟

loveishere
چهارشنبه 24 بهمن 1386, 11:38 صبح
راستی فراموش کردم، لطفا حجم فایل هم به header بفرستید چون زمان دانلود حجم فایل رو unknown شناسایی می کنه

mahdi_negahi
چهارشنبه 24 بهمن 1386, 16:00 عصر
خیلی ممنون
درست شد

shocraneh
سه شنبه 20 بهمن 1388, 11:31 صبح
من از این روش استفاده کردم منتها با ویبی کدهام مشکل نداره منتها مقدار state در تابع DownloadFile صفر بر می گرده چون در کلاس ResumeDownload
از خطوط زیر پرش می کنه و دیگه ادامه نمی ده




If Not (objRequest.HttpMethod.Equals(HTTP_METHOD_GET) OrElse objRequest.HttpMethod.Equals(HTTP_METHOD_HEAD)) Then
objResponse.StatusCode = 501 ' Not implemented

ElseIf Not objFile.Exists Then



شرمنده خیلی ابتداییه
میشه توضیح بدین اصلا چرا از این روش استفاده میشه (لطفا سطح پایین بگین تا من بفهمم ) . فکر کنم برای فایل با حجم بزرگ کارایی داره

ealireza
شنبه 24 بهمن 1388, 00:30 صبح
این موضوع چاره داره
چارشم چیزی نیست جز نوشتن یه کلاس جدید


اگه یکی از دوستان بشینه سره فرصت با بررسی دقیق کار این سیستم یه کلاس رو تهیه کنه مشکل حل میشه .


موفق باشید

SalarSoft
شنبه 06 اسفند 1390, 20:44 عصر
نسخه جدید این کلاس همراه با قابلیت کنترل سرعت دانلود و توضیحات نحوه استفاده رو از اینجا دریافت کنید:

http://blog.salarcode.com/2012/02/aspnet-resumable-downloading.html

fakhravari
دوشنبه 08 آبان 1391, 02:57 صبح
نسخه جدید این کلاس همراه با قابلیت کنترل سرعت دانلود و توضیحات نحوه استفاده رو از اینجا دریافت کنید:

http://blog.salarcode.com/2012/02/aspnet-resumable-downloading.html
سلام اقای SalarSoft (http://barnamenevis.org/member.php?4890-SalarSoft) عزیز
در مورد قسمت ResumableDownload.ashx چون یک فایل در پروژه هست .
نمی توانستید اونم در کلاس بزارید که دیگه نیازی به فراخونی نباشه