PDA

View Full Version : سوال: ساخت دانلودر با دلفی



Emdad2001
یک شنبه 05 آذر 1391, 16:47 عصر
سلام

من میخواستم تو برنامه ام یک دانلودر داشته باشه یعنی اینکه فایل های مورد نیاز یا Update رو خودش دانلود کنه تا یک قسمتی جلو رفتم ولی هنوز مشکل داره البته دارم باهاش کار میکنم ولی میخوام بهتر بشه کد رو میزام نظر بدید، و اما مشکل !!

1- چجوری میتونم عددی رو که به بایت میده رو به مگابایت و کیلوبایت تبدیل کنم
2- چرا وقتی برنامه دانلودش تمام میشه برای بار دوم دانلود نمی کنه یعنی خطا میده مجبور میشم برنامه را ببندم و دوباره باز کنم؟

بگذریم خیلی سوال کردم

var
idHTTP:TIdHTTP;
MS:TMemoryStream;
begin
try
IdIcmpClient1.Host:='8.8.8.8';
IdIcmpClient1.Ping();
except

end;
if (IdIcmpClient1.ReplyStatus.TimeToLive>40)then
begin
//---------------------------Connected to the internet--------------------------
idHTTP:=TIdHTTP.Create(nil);
ProgressBar1.Refresh;
Gauge1.Refresh;
try
MS:=TMemoryStream.Create;
idHTTP1.Get(Label4.Caption,MS);
MS.SaveToFile(Edit1.Text);
finally
idHTTP1.Free;
MS.Free;
end;
end
else
begin
//---------------------Disconnected from the internet---------------------------


end;

و برای تنظیم IdHttp

procedure TDownload_Form2.IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode;
AWorkCount: Int64);
begin
if AWorkMode=wmRead then
begin
RichEdit1.Lines.Add('درحال دریافت : '+IntToStr(AWorkCount));
ProgressBar1.Position:=AWorkCount;
Gauge1.Progress:=AWorkCount;
Application.ProcessMessages;
end
else
begin
RichEdit1.Lines.Add('Write '+IntToStr(AWorkCount));
end;
end;


procedure TDownload_Form2.IdHTTP1WorkBegin(ASender: TObject;
AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
if AWorkMode=wmRead then
Label2.Caption:=IntToStr(AWorkCountMax);
ProgressBar1.Max:=AWorkCountMax;
Gauge1.MaxValue:=AWorkCountMax;
Gauge1.Progress:=0;
ProgressBar1.Position:=0;
end;



procedure TDownload_Form2.IdHTTP1WorkEnd(ASender: TObject;
AWorkMode: TWorkMode);
begin
if AWorkMode=wmRead then
ProgressBar1.Free;
Gauge1.Free;
Self.Close;
end;

Ananas
یک شنبه 05 آذر 1391, 17:16 عصر
سلام.
کیلو یعنی هزار و مگا یعنی هزار-هزار یعنی میلیون. برای تبدیل بایت به کیلو و مگا، جای این هزار ها از 1024 استفاده کنید و عدد رو تقسیم کنید به : به ترتیب 1024 و (1024 * 1024).

بهروز عباسی
یک شنبه 05 آذر 1391, 17:58 عصر
درود
کد زیر رو امتحان کن


....
function StrFormatByteSize(dw: int64; szBuf: pansichar; uiBufSize: UINT)
: pansichar; stdcall; external 'shlwapi.dll' name 'StrFormatByteSize64A';

implementation
...
function FileSizeToStr(SizeInBytes: int64): string;
var
arrSize: array [0 .. 255] of AnsiChar;
begin
StrFormatByteSize(SizeInBytes, arrSize, Length(arrSize) - 1);
SetString(Result, pansichar(@arrSize[0]), sizeof(arrSize));
end;


موفق باشید.

Emdad2001
یک شنبه 05 آذر 1391, 18:58 عصر
سلام.
کیلو یعنی هزار و مگا یعنی هزار-هزار یعنی میلیون. برای تبدیل بایت به کیلو و مگا، جای این هزار ها از 1024 استفاده کنید و عدد رو تقسیم کنید به : به ترتیب 1024 و (1024 * 1024).

یعنی Max رو دوبار به 1024 ضرب کنم ؟ درست متوجه شدم ؟

Emdad2001
یک شنبه 05 آذر 1391, 19:03 عصر
درود
کد زیر رو امتحان کن


....
function StrFormatByteSize(dw: int64; szBuf: pansichar; uiBufSize: UINT)
: pansichar; stdcall; external 'shlwapi.dll' name 'StrFormatByteSize64A';

implementation
...
function FileSizeToStr(SizeInBytes: int64): string;
var
arrSize: array [0 .. 255] of AnsiChar;
begin
StrFormatByteSize(SizeInBytes, arrSize, Length(arrSize) - 1);
SetString(Result, pansichar(@arrSize[0]), sizeof(arrSize));
end;


موفق باشید.

مرسی لطف کردین میشه توضیح بدید من چجوری از این استفاده کنم ؟ آخه من مبتی هستم :(

Emdad2001
یک شنبه 05 آذر 1391, 19:08 عصر
مرسی ممنون آقای عباسی درست شد :)

ولی سوال دوم منو نگفید من با دستور


Idhttp1.disconnect

قطع میکنم حالا میشه توضیح بدین بی زحمت

Ananas
یک شنبه 05 آذر 1391, 19:11 عصر
یعنی Max رو دوبار به 1024 ضرب کنم ؟ درست متوجه شدم ؟
نمی دونم اینجا تو کد شما max چه چیزیه ولی برای تبدیل بایت به کیلو بایت، باید عدد رو به 1024 تقسیم کنید و برای تبدیل بایت به مگابایت باید دو بار به 1024 تقسیم کنید :

function ByteToKByte(size : Int64):Int64;
begin
Result := size div 1024;
end;
function ByteToMByte(size : Int64):Int64;
begin
Result := size div (1024 * 1024);
end;

Emdad2001
یک شنبه 05 آذر 1391, 19:52 عصر
نمی دونم اینجا تو کد شما max چه چیزیه ولی برای تبدیل بایت به کیلو بایت، باید عدد رو به 1024 تقسیم کنید و برای تبدیل بایت به مگابایت باید دو بار به 1024 تقسیم کنید :

function ByteToKByte(size : Int64):Int64;
begin
Result := size div 1024;
end;
function ByteToMByte(size : Int64):Int64;
begin
Result := size div (1024 * 1024);
end;


ممنون منظورم از Max ... AWorkCountMax بود ولی درست شد، ولی اگه میشه بگید چجوری دوباره دانلود کنم فکر میکنم مشکل از idhhtp باشه در حالی که از اخر free میکنم ولی باز دوباره نمی تونم دانلود کنم

Felony
یک شنبه 05 آذر 1391, 20:37 عصر
چه خطایی میده ؟ حدس بزنیم ؟

Emdad2001
یک شنبه 05 آذر 1391, 22:28 عصر
چه خطایی میده ؟ حدس بزنیم ؟

Access violation ad address 00000000050EAD8 in module 'Project1.exe'. Read of address 00000000000000.

Felony
یک شنبه 05 آذر 1391, 22:52 عصر
به خاطر اينكه Progressbar و Gauge رو بار اول تو رويداد OnWorkEnd آزاد كردي و بار دوم وجود ندارن كه ازشون استفاده كني ، به جاي آزاد كردنشون فقط position شون رو 0 كن .

Emdad2001
دوشنبه 06 آذر 1391, 00:27 صبح
به خاطر اينكه Progressbar و Gauge رو بار اول تو رويداد OnWorkEnd آزاد كردي و بار دوم وجود ندارن كه ازشون استفاده كني ، به جاي آزاد كردنشون فقط position شون رو 0 كن .

نه مال اون نبود همانطور که گفتین عمل کردم اما درست نشد !! من idHttp1.free در پایان انجام میدم مال اون نیست ؟ بار اول همچی درسته بدون هیچ خطایی اما برای باره دوم که همون ادرس رو دانلود میکنم خطا میده :(

Felony
دوشنبه 06 آذر 1391, 05:25 صبح
عملیات ساخت MemoryStream ت رو ببر خارج از بلوک try پیش همون idHttp :

var
idHTTP:TIdHTTP;
MS:TMemoryStream;
begin
try
IdIcmpClient1.Host:='8.8.8.8';
IdIcmpClient1.Ping();
except

end;
if (IdIcmpClient1.ReplyStatus.TimeToLive>40)then
begin
//---------------------------Connected to the internet--------------------------
idHTTP:=TIdHTTP.Create(nil);
ProgressBar1.Refresh;
Gauge1.Refresh;
try
MS:=TMemoryStream.Create;
idHTTP1.Get(Label4.Caption,MS);
MS.SaveToFile(Edit1.Text);
finally
idHTTP1.Free;
MS.Free;
end;
end
else
begin
//---------------------Disconnected from the internet---------------------------


end;

اون Application.ProcessMessages رو هم حذف کن .

Emdad2001
دوشنبه 06 آذر 1391, 06:38 صبح
سلام آقا ماهان ولی بازم درست نشد :(


idHTTP:=TIdHTTP.Create(nil);
MS:=TMemoryStream.Create;
ProgressBar1.Refresh;
Gauge1.Refresh;
try
idHTTP1.Get(Label4.Caption,MS);
MS.SaveToFile(Edit1.Text);
finally
idHTTP1.Free;
MS.Free;
end;



if AWorkMode=wmRead then
begin
RichEdit1.Lines.Add('درحال دریافت : '+IntToStr(AWorkCount)+'بایت');
ProgressBar1.Position:=AWorkCount;
Gauge1.Progress:=AWorkCount;
//Application.ProcessMessages;
end
else
begin
RichEdit1.Lines.Add('Write '+IntToStr(AWorkCount));
end;



if AWorkMode=wmRead then
Label2.Caption:=(FileSizeToStr(AWorkCountMax));
ProgressBar1.Max:=AWorkCountMax;
Gauge1.MaxValue:=AWorkCountMax;
Gauge1.Progress:=0;
ProgressBar1.Position:=0;


تازه وقتی بخوای idHttp1.disconnect کنی بازم همین پیغام رو میده فکر کنم زیر سر TMemoryStrem و یا idHttp1

Emdad2001
دوشنبه 06 آذر 1391, 06:51 صبح
درضمن مشکل رو پیدا کردم گفتم زیر سر این دوتا هست از اخر Free نکردم درست شد ولی اگه free نکنم چه اتفاقی می افته ؟


idHTTP:=TIdHTTP.Create(nil);
MS:=TMemoryStream.Create;
ProgressBar1.Refresh;
Gauge1.Refresh;
try
idHTTP1.Get(Label4.Caption,MS);
MS.SaveToFile(Edit1.Text);
finally
IdHTTP1.Disconnect;
MS.Clear;
//idHTTP1.Free;
//MS.Free;

Felony
دوشنبه 06 آذر 1391, 07:28 صبح
نباید این مشکل پیش بیاد ، من الان همون کد بالا رو چند بار تست کردم ، اگر اونها رو Free نکنی تو برنامت Memory Leak خواهی داشت ، اون Owner مربوط به idHtttp رو فرم برنامت قرار بده ( Self ) تا خود فرم موقع آزاد شدن اون رو هم آزاد کنه و فقط Memory Stream رو دستی آزاد کن ببین باز هم مشکل داری .

Emdad2001
دوشنبه 06 آذر 1391, 20:01 عصر
نباید این مشکل پیش بیاد ، من الان همون کد بالا رو چند بار تست کردم ، اگر اونها رو Free نکنی تو برنامت Memory Leak خواهی داشت ، اون Owner مربوط به idHtttp رو فرم برنامت قرار بده ( Self ) تا خود فرم موقع آزاد شدن اون رو هم آزاد کنه و فقط Memory Stream رو دستی آزاد کن ببین باز هم مشکل داری .

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


procedure TForm1.Button1Click(Sender: TObject);
var
idHTTP:TIdHTTP;
MS:TMemoryStream;
begin
idHTTP:=TIdHTTP.Create(nil);
MS:=TMemoryStream.Create;
try
idHTTP1.Get(Label1.Caption,MS);
MS.SaveToFile(Edit1.Text);
finally
IdHTTP1.Free;
MS.Free;
end;

end;

Felony
دوشنبه 06 آذر 1391, 21:20 عصر
خدایی مارو گیر آوردی ها ، برداشتی کامپوننت idHttp رو ساختی بعد از idHttp1 برای دریافت فایل استفاده کردی و در آخر آزادش کردی ، این idHttp1 رو هم حتما رو فرم قرار دادی ، بعد از اجرای اول آزاد میشه و در بار بعد idHttp ساخته میشه نه idHttp1 ، پس idHttp1 وجود نداره و AV میده .


var
IdHTTP: TIdHTTP;
MS: TMemoryStream;
begin
IdHTTP := TIdHTTP.Create(nil);
MS := TMemoryStream.Create;
try
IdHTTP.Get(Label1.Caption, MS);
MS.SaveToFile(Edit1.Text);
finally
IdHTTP.Free;
MS.Free;
end;
end;

Mask
دوشنبه 06 آذر 1391, 21:32 عصر
خدایی مارو گیر آوردی ها ، برداشتی کامپوننت idHttp رو ساختی بعد از idHttp1 برای دریافت فایل استفاده کردی و در آخر آزادش کردی ، این idHttp1 رو هم حتما رو فرم قرار دادی ، بعد از اجرای اول آزاد میشه و در بار بعد idHttp ساخته میشه نه idHttp1 ، پس idHttp1 وجود نداره و AV میده .


var
IdHTTP: TIdHTTP;
MS: TMemoryStream;
begin
IdHTTP := TIdHTTP.Create(nil);
MS := TMemoryStream.Create;
try
IdHTTP.Get(Label1.Caption, MS);
MS.SaveToFile(Edit1.Text);
finally
IdHTTP.Free;
MS.Free;
end;
end;
عاقبت کپی پیست همینه اخوی.
دوست من ، کد رو بخون ببین چی نوشتی. یه idhttp1 نوشتی یه idhttp.

Emdad2001
دوشنبه 06 آذر 1391, 22:46 عصر
مرسی Gold از راهنمایی تون آخه بابا از اول اگه نگاه کنید من همین کد رو گذاشتم چیزی که تغییر نکرده من که از اول گفتم چیزی بلد نیستم شما دیر متوجه شدید . حالا ببخشید آقا ماهان که به زحمت افتادید، حالا بگذریم یعنی من باید idHttp1 رو از روی فرم حذف کنم ؟ یا باشه ؟

Felony
دوشنبه 06 آذر 1391, 22:58 عصر
کدی که من قرار دادم رو دیدید ؟ از idHttp1 توش استفاده شده بود که بهش نیاز باشه ؟ کمی دقت کنید و کدهای این و اون رو همینطور کپی نکنید .