Hemen hemen hergün internetten birşeyler indirip duruyoruz. Kimi zaman çeşitli resim dosyaları, kimi zaman videolar kimi zamanda işimizle alakalı yada değil başka materyaller. Bu dosyaları bilgisayarımıza indirirken çoğu zaman indirme yönetici programlarından istifade ediyoruz. FlashGet, GetRight gibi. Bu programların indirilecek dosyayı bir kaç parça halinde indirme özellikleri olduğu gibi, herhangi bir bağlantı sorununda kaldıkları yerden devam edebilme gibi akıllı özellikleri var. Bizlerin onları tercih etmesindeki yegane neden de bu zaten. Peki hiç düşündünüz mü, internetten bir dosya bir kaç parça halinde nasıl indirilebiliyor ? Yada indirme işleminde sorun olduğunda kalınan yerden indirmeye nasıl devam edilebiliyor ?
Bir önceki makalemde BITS konusunu ele almıştım. BITS’de dosyalarımızı sessiz sedasız indirme yeteneğine sahipti. Aynı zamanda kaldığı yerden devam da edebiliyordu. Ancak arka planda ne gibi bir teknoloji kullandığı hakkında hiçbir fikrimiz yok. Nasıl yapıyor da internet üzerindeki bir dosyayı belirli bir yerinden okumaya başlayabiliyordu.. Aynı sorular diğer indirme yöneticileri için de sorulabilir elbette. İşte bu makalemizde bu konuya biraz ışık tutmaya çalışacağız. Ben sizlerle paylaşacağım örneğimde aşağıda göreceğiniz resim dosyasını bilgisayarıma indirmeye çalışacağım. Siz başka bir kaynak üzerindeki herhangi bir dosyayı deneyebilirsiniz. İşte indireceğimiz dosya
İnternet üzerindeki herhangi bir dosyayı indirme işlemimizi Delphi ile birlikte gelen Indy kütüphanesinden faydalanarak yapacağız. Ben bu örneği Delphi 2009 üzerinde yazacağım. Daha önceki Delphi sürümlerinde Indy komut setlerinin değişik olabileceğini ancak ufak bir araştırma ile eski Delphi sürümlerine de adapte edilebileceğini düşünüyorum.
Bizim kullanacağımız bileşen TIdHttp aslında internet üzerinden herhangi bir veri kaynağını yerel bilgisayarınıza alabilmeniz için geliştirilmiş son derece güçlü bir bileşen. Biz bu bileşeni yukarıdaki resim dosyasını indirmek için kullanacağız. TIdHTTP bileşeninin makalemize konu olan parçalı indirme için Range gibi güçlü bir özelliği mevcut. Biz de bundan istifade edeceğiz. Ancak daha detay malümatlara girmeden evvel, indirmek istediğimiz dosyanın boyutunu öğrenebilmemiz gerekir. Boyutunu bilmediğimiz bir dosyayı istediğimiz sayıda parçaya da ayıramayız. Bunun için de yine TIdHttp’den yararlanacağız.
Örneğimiz, verilen bir internet adresindeki dosyayı lokalde belirttiğimiz bir yere belirttiğimiz isimde; istediğimiz kadar parçaya ayırarak indirecek. İndirme işlemini hız için TThread sınıfından istifade ederek gerçekleştirecek. Ancak örneğimiz, suspended download’ı desteklemiyor olacak. Yani indirmek için parçalara ayırdığımız thread’lerden birisinin hatalı sonlanması durumunda dosyamız düzgün bir şekilde indirilmemiş olacak. Lâkin vereceğimiz bilgiler ile, örneğimizi geliştirip indirilemeyen, yarım kalan parçaların indirilmesini sağlayabilecek kodları da pekâla yazabilirsiniz. Evet artık kodlarımıza başlamanın zamanı geldi sanırım:

  TRange = record
    StartPosition,
    EndPosition  : Integer;
  end;

  TDownloader = class;

  TDownloadThread = class(TThread)
  private
    fOwner : TDownloader;
    fUrl,
    fFileName : String;
    fRange : TRange;
  protected
    procedure Execute; override;
  public
    constructor Create(const AOwner : TDownloader; const AUrl, AFileName : String; ARange : TRange);
  end;

  TOnDownloadComplete = procedure(const FileName : String; const WorkTime : DWord) of object;
  TDownloader = class
  private
    fUrl,
    fFileName : String;
    fPart     : Integer;
    fWorkTime : DWord;
    Section   : TCriticalSection;

    fOnDownloadComplete : TOnDownloadComplete;

    procedure Notify;
  public
    constructor Create;
    destructor Destroy; override;

    procedure Download(const Url, FileName : String; const Part : Integer = 10);

    property OnDownloadComplete : TOnDownloadComplete read fOnDownloadComplete write fOnDownloadComplete;
  end;
Yukarıda gördüğünüz gibi indirme işlemleri için TRange isimli bir recordumuz, TDownloadThread ve TDownloader isimli birer sınıfımız mevcut. TDownloader sınıfının Download metodu Url parametresi ile aldığı internet üzerindeki bir dosyayı FileName parametresi ile belirttiğimiz isimle makinamıza indirecek. İndirme işlemi için ise TDownloadThread sınıfından istifade edecek. Part parametresi varsayılan olarak indirilecek dosyanın 10 parçada indirilmesini öngürüyor. Bu da 10 adet TDownloadThread nesnesi oluşturulacak ve çalıştırılacak demektir. TRange record’u bizim için hayati bir öneme sahip, lâkin henüz onu izah etmenin zamanı değil. Biz kodlarımıza devam edelim müsaadeniz ile;

{ TDownloader }

constructor TDownloader.Create;
begin
  inherited;

  Section := TCriticalSection.Create;
end;

destructor TDownloader.Destroy;
begin
  if Assigned(Section) then Section.Free;

  inherited;
end;

procedure TDownloader.Download(const Url, FileName: String;
  const Part: Integer);
var
  http : TIdHttp;
  Size : Int64;
  fs : TFileStream;
  sBuff : String;

  iCounter,
  iByteCount: Integer;
  Ranges : array of TRange;
begin
  fUrl := Url;
  fFileName := FileName + '.tmp';
  fPart := Part;

  http := TIdHttp.Create(nil);
  fs := TFileStream.Create(fFileName, fmCreate or fmShareDenyNone);
  try
    http.Head(url);
    Size := http.Response.ContentLength;
    if Size > 0 then
    begin
      SetLength(sBuff, Size);
      FillChar(Pointer(sBuff)^, Size, '0');
      fs.WriteBuffer(Pointer(sBuff)^, Size);
    end;
  finally
    fs.Free;
    http.Free;
  end;

  SetLength(Ranges, Part);
  iByteCount := Size div Part;

  Ranges[0].StartPosition := 0;
  Ranges[0].EndPosition   := iByteCount;

  for iCounter := 1 to Part - 1 do
  begin
    Ranges[iCounter].StartPosition  := (iCounter * iByteCount) + 1;
    Ranges[iCounter].EndPosition    := (iCounter + 1) * iByteCount;
  end;

  Ranges[Part-1].EndPosition := Size;

  fWorkTime := GetTickCount;
  for iCounter := Low(Ranges) to High(Ranges) do
  begin
    with TDownloadThread.Create(
                                Self,
                                fUrl,
                                fFileName,
                                Ranges[iCounter]
                               ) do Resume;
    Sleep(100);
  end;
end;

procedure TDownloader.Notify;
var
  NewFileName : String;
begin
  Section.Enter;
    Dec(fPart);
    if fPart = 0 then
    begin
      NewFileName := StringReplace(fFileName, '.tmp', '', [rfReplaceAll]);
      RenameFile(fFileName, NewFileName);

      if Assigned(fOnDownloadComplete) then
        fOnDownloadComplete(NewFileName, GetTickCount - fWorkTime);
    end;
  Section.Leave;
end;
TDownloader sınıfımızın constructor’unda TCriticalSection türünde bir nesne oluşturulduğunu görüyorsunuz. Bu nesne daha sonra Notify metodunun içerisinde kullanılmak üzere oluşturuluyor. TCriticalSection’lar genel olarak multi threaded programlamada kodunuzun kritik kısımlarına başka thread’lerin girmesine engel olmak adına mevcutturlar. TDownloader sınıfının Notify metodu, her TDownloadThread sınıfının bitişinde otomatikman çalıştırılacaktır. Tüm download thread’lerinin bitmesi dosyamızın başarı ile indirildiğinin göstergesi olacağından Notify metodunda bir event tetiklenmektedir. Dolayısı ile tüm thread’lerin herhangi bir zaman diliminde girebilecekleri bir metod olan Notify’ın koruma altına alınması gerekir. Bu koruma TCriticalSection.Enter/TCriticalSection.Leave ile sağlanır. TCriticalSection.Enter çağrısını geçtikten sonra, yani bir thread kod bloğumuzu işletirken bir başka thread TCriticalSection.Enter bloğunda sanki bir breakpoint varmış gibi beklemeye başlayacaktır. Taa ki TCriticalSection.Leave çağrısı işletilene kadar. Critical Section’lar şu bir kaç satırda izah edilebilecek kadar basit ve işlevsiz hususlar değillerdir. Multi-threaded programlamada son derece önemli kullanım sahaları vardır. Ancak konumuz bu olmadığı için daha derinlemesine anlatmak istemiyorum.
Critical section’ı neden kullandığımı izah ettikten sonra, biraz da TDownloader.Download metodundan bahsedelim. Bu metodun içinde TFileStream sınıfı vasıtası ile verilen isimdeki dosya verilen yolda oluşturulur. Ancak oluşturulma parametresindeki fmShareDenyNone‘a dikkatinizi çekmek isterim. TFileStream’in dosya erişimleri ile ilgili pek çok parametresi vardır. Yazmaya karşı korumalı, okumaya karşı korumalı, exclusive(yazma/okuma) korumalı, yada korumasız gibi. fmShareDenyNone parametresi ile oluşturduğumuz bu dosyanın başka uygulamalar/thread’ler tarafından okunabileceğini yada yazılabileceğini ifade etmiş oluyoruz.
Ardından TIdHTTP sınıfının Head metodunu çağırıyoruz. Bu metodu çağırmamızın sebebi, internet üzerinden download etmek istediğimiz dosyanın veri büyüklüğünü bilme zorunluluğumuz. Daha önce de ifade ettiğim gibi veri büyüklüğünü bilemediğimiz bir dosyayı parçalara bölemeyiz. Indy’nin pek çok bileşeninde Request ve Response property’lerine rastlamanız mümkün. Request genel anlamda karşı taraftan istekler; Response ise karşı tarafın verdiği yanıtlar olarak düşünülebilir. Biz uzaktaki bir dosyanın veri büyüklük bilgisini TIdHTTP’nin Head metodu ile istediğimize göre, aradığımız değer de Response(yanıt) içinde olacaktır. Response.ContentLength bize internet üzerindeki dosyanın veri büyüklüğünü verecektir.
Artık dosyanın uzunluk bilgisini aldıktan sonra diğer kısımlara geçebiliriz. Bu örneğin en can alıcı noktalarından bir tanesi ise aşağıdaki satırlarda gizlidir;

    if Size > 0 then
    begin
      SetLength(sBuff, Size);
      FillChar(Pointer(sBuff)^, Size, '0');
      fs.WriteBuffer(Pointer(sBuff)^, Size);
    end;
Yukarıdaki kod, sBuff isimli string değişken için hafızada dosyanın büyüklüğü kadar yer ayırmasını ardından içeriğinin sıfırlanmasını ve lokaldeki dosyamıza yazılmasını sağlar. Örneğin, indireceğimiz dosya 10 kb olsa, bu rutin hafızada 10 kb’lık bir yer ayıracak, içini sıfırlarla dolduracak ve hafızada ayrılmış veriyi bizim lokaldeki dosyamızın içine yazacak. Kısacası lokaldeki dosyamızın içinde 10240 adet 0(sıfır) olacak.
Peki bunu neden yapıyoruz ? Aslında nedeni thread kullanmamız. Bildiğiniz gibi thread’ler başına buyruk kod parçacıklarıdır. Kendi hallerinde çalışırlar, diğerlerine pek bulaşmazlar. Ancak tüm thread’lerin ortak kullanacakları bir kaynak varsa o zaman thread programlamada biraz dikkat gerekir. Bu örneğimizde tüm download thread’ler uzaktaki bir dosyanın belli byte’larını okuyacaklar bu hususta birbirlerinden bağımsızlar. Ancak hepsi aynı dosyaya yazacak. İşte bu hususta bağımsız değiller.. Risklere açık bir durum söz konusu. Lokaldeki dosyamıza yazacak olan thread’lerin ardışıl olarak çalışmaları söz konusu olsa idi, o zaman yine bir sorun olmayabilirdi. Kısa bir örnek vermek gerekir ise;
Diyelim ki internet üzerinden indirmek istediğimiz dosya bir text dosya olsun. İçerisinde de “Merhaba Dünya” yazısı olsun. Bu text dosyayı indirmek için iki ayrı thread’imiz olsun. Birinci thread’in “Merhaba” bilgisini, diğerinin ise “Dünya” bilgisini aldığını düşünelim. Yazacakları dosya aynı olduğu için, birinci thread’in dosyaya yazmaya başladığını düşünün. Bildiğiniz gibi TStream sınıfından türemiş tüm sınıflar herhangi bir stream’e veri yazdıklarında stream’in pozisyon bilgisini tutan sayacı arttırırlar. Öyle bir an geldiğini düşünün ki, birinci thread “Mer” yazabilmişken ikinci thread’de dosyayı açıp içine Dünya yazmaya başlamış olsun. Birinci thread “haba” yazıp dosyayı kapattığında aslında ikinci thread birinci thread’in yazdıklarının üstüne yazmış olur. Ve dosya o şekilde saklanır.
Bu ve buna benzer bir çok garip durumla karşılaşılabilir. Thread’lerin belirli bir sırada çalışması garanti olsa, yani önce birinci thread çalışıp sonlansa ve ardından ikincisi devreye girip sonlansa tahmin edeceğiniz gibi hiç bir sorun olmaz. Ancak, bu ihtimalli bir durumdur. Birinci thread’in indirmesi gereken veriler daha uzun olabilir ve ikincisinin çalışma zamanından daha uzun bir çalışma zamanına sahip olabilir. Yine makalelerimizden birisinde daha önce yazdığımız gibi, Thread’leri sıraya soksak bu seferde thread kullanmamızın bir anlamı kalmayacak. Biz indirme işleminin ve yazma işleminin paralel yürütülmesini istiyoruz.
İşte tüm bu sebeplerden ötürü, benim aklıma gelen ilkel yöntem internet üzerinden indirilecek olan dosyanın büyüklüğü kadar lokal dosyada sıfır oluşturmak. Bu durumda her thread lokal dosyada hangi pozisyondan başlayarak kaç byte yazacağını bildiği için, diğer thread’lerin yazacağı bilgilerle çakışmamış olacağız.
Metin: Merhaba Dünya
Thread 1 : 1-8 arası karakterleri indir.
Thread 2 : 9-13 arası karakterleri indir.
Thread 1 : Lokal dosyanın 1 pozisyonuna konumlan. 8 byte veri yaz.
Thread 2 : Lokal dosyanın 9 pozisyonuna konumlan 5 byte veri yaz.
Yukarıdaki senaryodan görebileceğiniz üzere iki yada daha fazla thread aynı anda aynı dosyaya erişse ve o dosya üzerinde yazma işlemi yapsa da herhangi bir sorun oluşmayacaktır. Çünkü her thread dosyanın ayrı bir yerine yazmaktadır.
Bu kısmı da anlattıktan sonra, TDownloader.Download metoduna geçilen Part parametresi üzerinde durmamız gerekiyor. Part parametresi indirme işlemi için kaç adet thread kullanmak istediğimizi ifade ediyor. Part parametresinin değerine göre internet üzerinden indirilecek olan dosyanın hangi byte aralıklarında indirilmesi gerektiğini ve lokaldeki dosyaya hangi aralıklarla yazmamız gerektiğini bulabiliyoruz. Örneğin indirmek istediğimiz dosya, 123.456 byte olsun ve Part parametremizde 10 olsun. Bu durumda 123.456 / 10 = 12.345 byte’lık parçalar halinde indirme yapacağız demektir. Bu da; 0-12345 , 12346-24691, 24692-37036 … gibi aralıklara sahip olacağız anlamına gelir. TDownloader.Download metodunun geri kalan kısımları bu aralık değerlerini hesaplamak ve download thread’lerini çalıştırmaktan ibaret.
Şimdi arzu ederseniz, download işlemini yapan thread’imizin kodlarına yakından bir bakalım:

{ TDownloadThread }

constructor TDownloadThread.Create(const AOwner : TDownloader; const AUrl, AFileName : String; ARange : TRange);
begin
  inherited Create(true); // Thread durur vaziyette olsun..
  FreeOnTerminate := true; // işi bitince free olsun..

  fFileName := AFileName;
  fRange := ARange;
  fUrl := AUrl;
  fOwner := AOwner;
end;

procedure TDownloadThread.Execute;
var
  http: TIdHttp;
  fs  : TFileStream;
  ms  : TMemoryStream;
begin
  inherited;

  http:= TIdHttp.Create(nil);
  fs := TFileStream.Create(fFileName, fmOpenWrite or fmShareDenyNone);
  ms := TMemoryStream.Create;

  try
    http.Request.Range := Format('%d-%d', [fRange.StartPosition, fRange.EndPosition]);
    http.Get(fUrl, ms);

    fs.Position := fRange.StartPosition;
    ms.Position := 0;
    fs.CopyFrom(ms, ms.Size);
  finally
    fs.Free;
    ms.Free;
    http.Disconnect;
    http.Free;
  end;

  fOwner.Notify;
end;
Thread’imiz ilk oluşturulduğunda henüz uyur vaziyettedir. Oluşturulma kodları tamamlanınca TDownloader.Download metodunun içindeki Resume çağrısı vasıtası ile çalıştırılacak ve Execute metoduna dallanılacaktır. Execute metodunda, lokalimizdeki dosyanın sadece yazma amacı ile açıldığını gözlemleyebilirsiniz. Ardından en önemli komut olarak Request.Range’e internet üzerinden indirilecek dosyanın hangi byte’larının indirileceği bilgisi aktarılıyor. Ardından Get metodu bizim belirttiğimiz Url’deki dosyanın Range property’sinde belirttiğimiz başlangıç ve bitiş byte’ları kadar bilgiyi okuyup ikinci parametresindeki TStream türündeki stream’e yazıyor. Biz burada internetten indirmek istediğimiz dosyanın ilgili byte’larını bir TMemoryStream‘de tutmayı uygun bulduk.
Ardından yine can alıcı bir nokta olarak, TMemoryStream sınıfından türemiş nesnemizin pozisyon işaretçisini en başa aldık. Ancak TFileStream türündeki nesnemizinkini ise, thread’in indirmeye başladığı başlangıç değerine aldık Eğer bir sihir varsa bu makalede o da bu kısımdır Sonrasında ise CopyFrom ile TMemoryStream’den okuyup TFileStream’e yazdık. Ve nihayet thread’imizin işini bitirdiğini belirtmek maksadı ile TDownloader nesnemize Notify metodunu çağırmak sureti ile haber verdik.
Bütün bu işlem döngüsü, tüm thread’ler için tamamlandığında, dosyamız internetten lokalimize indirilmiş oluyor. Kısa bir kullanımını verip, makaleyi tamamlayalım:

  TForm1 = class(TForm)
  ..
  ..
  ..
  private
    procedure DownloadComplete(const FileName : String; const WorkTime : DWord);
  public
  end;

var
  downloader : TDownloader;
..
..
..
// Memo1 TMemo türündedir.
procedure TForm1.DownloadComplete(const FileName: String;
  const WorkTime: DWord);
begin
  Memo1.Lines.Add(FileName + ' download işlemi ' + InttoStr(WorkTime) + ' ms. sürdü.');
  if downloader <> nil then FreeAndNil(downloader);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if not Assigned(downloader) then downloader := TDownloader.Create;
  downloader.OnDownloadComplete := DownloadComplete;
  downloader.Download('http://www.tugrulhelvaci.com/wp-content/uploads/turboman.jpg', 'c:\turboman.jpg', 5);
end;
Bir sonraki makalemizde görüşmek ümidi ile,
Saygılar, sevgiler..
“TIdHTTP Partial Download(Parça Parça Download)” için 20 Yorum
Olcay DAĞLI diyor ki:	
03 Haziran 2009, 18:49	
Hocam gerçekten harika olmuş, kesinlikle her programcının, yazdıkları programların exe update işlemlerinde kullanması gereken güzel bir başucu kodu olmuş. Eline emeğine sağlık…
Cevapla	
Tuğrul HELVACI diyor ki:	
04 Haziran 2009, 04:35	
Teşekkür ederim olcay, işe yarar bir şeyler yapabiliyorsak ne mutlu bize.
Cevapla	
Önder Önvermez diyor ki:	
02 Aralık 2009, 00:27	
Teşekkürler.
Cevapla	
Fatih diyor ki:	
18 Aralık 2009, 22:26	
Slm;
Yazınızı okudum ancak deneyemedim acaba bana yardımcı olabilirmisiniz. Bu kodların çalışan halleri mevcutsa almak isterim . Teşekkürler.
Cevapla	
Tuğrul HELVACI diyor ki:	
25 Aralık 2009, 13:51	
Nerede sorun yaşadınız Fatih bey ? Detaylandırabilirseniz yardımcı olabilirim.
Cevapla	
mehmet diyor ki:	
18 Nisan 2010, 20:52	
Hocam makalenizi okudun.Ancak pek çözemedim.
Bir örnek verip kafamızdaki soruları netleştirebilirmisiniz.
Saygılar…
Cevapla	
Tuğrul HELVACI diyor ki:	
19 Nisan 2010, 02:20	
Bu makalede neyi çözemediniz ? En son bölümde kullanımına ait bir örnek de vermiştim.
Cevapla	
Mehmet diyor ki:	
05 Nisan 2011, 23:08	
Hocam Makaleniz çok güzel .
Ben delphiyi hobi olarak kullanıyorum.ama verdiğiniz kodları delphi nin hangi alanlarına yazacağımı çözemedim.Bu dosyayı bana gönderemezmisiniz.Rica Etsem
Saygılarımla…
Cevapla	
Tuğrul HELVACI diyor ki:	
07 Nisan 2011, 03:38	
Mehmet Bey, burada paylaştığım kodları Delphi’de nasıl kullanacağınızı bilemiyorsanız inanın projenin kaynak kodlarını göndermem size hiç bir fayda sağlamayacaktır. Mümkün mertebe ileri seviye konuları paylaşmaya gayret ediyorum sitemde. Paylaşımlarımın sizin için daha faydalı olabilmesi adına Delphi konusundaki temel bilgilerinizi biraz daha genişletmeyi tercih edebilirsiniz.
Cevapla	
Mehmet diyor ki:	
12 Nisan 2011, 23:25	
Hocam eleştirinizde haklısınız ama o kadarda bilmiyor sayılmam herşey tamam da sadece şurda bir hatam var
Section : TCriticalSection;
[DCC Error] Unit1.pas(37): E2003 Undeclared identifier: ‘TCriticalSection’
bu hatayı veriyor burda yardim ederseniz sevinirim.
Saygılarımla..
Cevapla	
Tuğrul HELVACI diyor ki:	
13 Nisan 2011, 03:49	
TCriticalSection SyncObjs.pas dosyasında tanımlanmıştır. Uses kımına SyncObjs eklemeniz gerekiyor.
Cevapla	
mahmut diyor ki:	
18 Temmuz 2011, 13:03	
Hocam elinize sağlık dökümanlarınız gerçekten harika.
Takıldığım bir konu var. Partial download ilerlemesini progressbar üzerinde nasıl gösterebiliriz ?
Cevapla	
ANIL diyor ki:	
16 Ekim 2011, 23:53	
Direk olarak yazılı ornek bir sources daha etkili olurdu. eğer elinde varsa sources şeklinde gönderirimisin lütfen?
Cevapla	
ANIL diyor ki:	
17 Ekim 2011, 16:56	
Merhaba, Kalan boyutu ve indirme hızını nasıl öğreniceğiz bunda aceba?
Cevapla	
Ali Gonenc diyor ki:	
30 Temmuz 2012, 07:07	
Merhaba
lisansli delphi 7 kullanicisiyim
delphi 7 de
http.Request.Range := Format(‘%d-%d’, [fRange.StartPosition, fRange.EndPosition]);
Request.Range “Range” malesef yok..
indy versionunu 10.1.5 ‘e yukselltim sorun devam etti
kod olarak
http.Request.ContentRangeStart:=fRange.StartPosition;
http.Request.ContentRangeEnd :=fRange.EndPosition;
denedim fakat olmadi
yardimci olursaniz cok sevinirim..
Cevapla	
Tuğrul HELVACI diyor ki:	
03 Ağustos 2012, 22:01	
Indy’nin 10x sürümlerinde Range özelliği olmalı.. Ama sizin mesajınızdan sonra küçük bir araştırma yaptım bende, sanırım Range property’si depreceted olmuş, onun yerine “Ranges” kullanılmasını öneriyorlar.
Cevapla	
Rahmi diyor ki:	
18 Kasım 2013, 22:25	
Merhaba
Dostum yazdığın makale çok işime yaradı fakat işin içinden çıkamadığım bir konu var.
Download etme esnasında PAUSE etme ve devam etme ?
Birkaç kod üzerinde oynama yaptım ama bir türlü çıkamadım işin içinden
// PART_2 Text dosyasında boyut varsa StartPosition ayarla.
if StrToInt(Form1.Part_2.Text) > 0 then
Ranges[0].StartPosition := StrToInt(Form1.Part_2.Text)
else
Ranges[0].StartPosition := 0;
//
procedure TDownloadThread.Execute;
.
..
..
http.Name := ‘A_’ + InttoStr(fRange.Sira);
http.OnWork := Form1.IdHTTP1Work;
// Olusan objeye isim verdim.
procedure TForm1.IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode;
AWorkCount: Int64);
if (ASender as TIdHTTP).Name = ‘A_0′ then
Part_2.Text := Inttostr((AWorkCount div 1024));
Manuel elle yazıdıgımda P2.text objesine devam etmesi gerekiyor ama sıfırdan baslıyor sebep nedir sizce?
Cevapla	
Tuğrul HELVACI diyor ki:	
19 Kasım 2013, 00:34	
Bu yapı pause edilmeye pek de müsait bir yapı değil. Çünkü belirli aralıktaki btye’ları TIdHttp’nin get metodu indiriyor. Dolayısı ile pause kodunun TIdHttp içinde yazılması icap eder ki bu da pek meşakkatli bir yöntem. Bu yapı yerine yine sitemde olan bulabileceğiniz BITS makalesi tam da sizin istediğiniz işi yapar. Hem o makaleden de görebileceğiniz gibi; BITS ile yapacağınız download’lar sistemi ve bağlantınızı zorlamayacak downloadlardır. İstediğiniz an pause edip istediğiniz an devam ettirebilirsiniz. Ayrıca; makinanızı kapatsanız dahi otomatikman kaldığı yerden download’a devam edebilme gibi güzel yetenekleri vardır. Dolayısı ile ; sitemde bulabileceğiniz BITS makalesine bir göz gezdirmenizde fayda olacağı kanaatindeyim.
Cevapla	
Rahmi diyor ki:	
19 Kasım 2013, 17:17	
Teşekkürler fakat BITS ile Proxy Script kullanmak mümkün müdür ?
Cevapla	
Tuğrul HELVACI diyor ki:	
20 Kasım 2013, 00:14	
Proxy script ?
Cevapla	
Önder Önvermez için yorum yazın
İsim (gerekli)
E-posta (gerekli)
Webite
Orhan diyor ki: Teşekkürler, güzel bir yazı kaleme almışsınız....
Coder22 diyor ki: Kitabın içeriği hakkında bir iki satır yazsaydınız...
Yüksel Demircioğlu diyor ki: Güel bir tespit olmuş.Teşekkürler......
emre diyor ki: tatukgis senin işini fazlasıyla görür...
emrah diyor ki: seydi arkadaşımızın sorduğu soru beni 2-3 haftadır...
gkyoeeo diyor ki: Спасибо за информацию!!!!!...
Absolute API Byte Arrays Class Reference COM CreateDesktop CreateProcess CreateRemoteThread CreateToolHelp32SnapShot DTS EnumDesktopProc EnumDesktops Function Pointer GetCurrentProcess GetIconInfo GetKeyState GetLastInputInfo GetProcessMemoryInfo GetStartupInfo Hacking Inheritance Interface JavaScript Method Pointer Module32First Module32Next OpenDesktop Persistance Pointer Procedure Pointer Process Process32First Process32Next Reqursion RTTI SetProcessWorkingSetSize SQL Server SwitchDesktop TerminateProcess Thread Untyped Parameters VirtualAllocEx VirtualFreeEx WaitForSingleObject WriteProcessMemory
Plugin WP FlashTime by horoscop 2009.org requires Flash Player 8 or better currency converter calculator.Plugin creat de horoscop | horoscop saptamanal | horoscop zilic | horoscop | play sonic games
Etiketler
Absolute Abstract Classes ActionScript Algoritma API Bug Byte Arrays Class Reference CloseHandle COM CreateDesktop CreateEvent CreateMutex CreateProcess CreateRemoteThread CreateSemaphore CreateToolHelp32SnapShot CreateWaitableTimer DeleteCriticalSection Delphi delphi 2010 DTS dynamic EnterCriticalSection EnumDesktopProc EnumDesktops Flash Function Pointer GetCurrentProcess GetIconInfo GetKeyState GetLastInputInfo GetProcessMemoryInfo GetStartupInfo GetThreadContext GetTickCount GetTickCount64 Hacking Inheritance InitializeCriticalSection Interface InterlockedCompareExchange InterlockedDecrement InterlockedExchange InterlockedExchangeAdd InterlockedIncrement JavaScript LeaveCriticalSection Method Pointer Module32First Module32Next MSSQL OpenDesktop OpenEvent OpenMutex OpenSemaphore OpenWaitableTimer Operator Overloading override Persistance Pointer Procedure Pointer Process Process32First Process32Next Query QueryInterface QueryPerformanceCounter Queue ReleaseMutex ReleaseSemaphore Reqursion ResetEvent ResumeThread RTTI SetEvent SetProcessWorkingSetSize SetThreadContext SetWaitableTimer Smilarity SORT SQL SQL Server static Stream SuspendThread SwitchDesktop TDateTime TerminateProcess TerminateThread Thread TInterfacedObject TValue Untyped Parameters virtual VirtualAllocEx VirtualFreeEx WaitForMultipleObjects WaitForSingleObject Weaver web service WriteProcessMemory ws-security WS-SecurityPolicy ws-trust _AddRef _Release
WP Cumulus Flash tag cloud by Roy Tanck requires Flash Player 9 or better.
Son Yorumlar
Nedir bu Thread’lerden çektiğimiz..! için Orhan
Bu kitabı almak lazım.. Ama ondan önce mümkünse dilimize kazandırmak lazım.. için Coder22
Statik ve dinamik metodlarin garip dunyasi için Yüksel Demircioğlu
Delphi ve Google Maps API için emre
DBX & DataSnap Hakkında Destek Talebi.. için emrah
Son Yazılar
Okuduğum & Okumaya Çalıştığım & Okuyacağım Kitaplar
Bir Ekmek, Bir Battaniye…
Bu kitabı almak lazım.. Ama ondan önce mümkünse dilimize kazandırmak lazım..
DBX & DataSnap Hakkında Destek Talebi..
Destek Talebi
Kategoriler
Genel (4)
IDE (1)
İşletim Sistemi (7)
Programlama (51)
.Net (3)
C# (2)
Delphi (51)
Grafik (2)
Internet (5)
Veritabanı (3)
Win32 (6)
Takvim
Aralık 2021
Pts
Sal
Çar
Per
Cum
Cts
Paz
« Eyl
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Arşivler
Eylül 2014 (1)
Aralık 2012 (2)
Mayıs 2012 (1)
Nisan 2012 (1)
Ağustos 2011 (1)
Nisan 2011 (2)
Haziran 2010 (1)
Mayıs 2010 (1)
Nisan 2010 (3)
Ağustos 2009 (1)
Temmuz 2009 (2)
Haziran 2009 (7)
Mayıs 2009 (32)
Bağlantılar
Bir Türkçe Sevdalısı..
Delphi Dünyası Forum
Delphi Türkiye Forum
Gürcan ÖZTÜRK
M.Fatih KÜÇÜKKELEPÇE
Memik YANIK Kişisel
Memik YANIK’ın Günlüğü
Nick Hodges
Sinan BARAN
Zafer Çelenk
Ziyaretçi Bilgileri
Ziyaret: 7 / 3888
Beğenilenler
Yeni Veri Tipleri ve Operator Overloading - 31 votes
Delphi 2010 (Weaver) ve TValue - 16 votes
Derinlemesine Threading..(3) - 13 votes
Derinlemesine Threading..(2) - 9 votes
DBX & DataSnap Hakkında Destek Talebi.. - 9 votes
XE2 Ile Gerceklesecek Evrime Hazir Misiniz? - 8 votes
Derinlemesine Threading..(1) - 7 votes
Win32 & .Net(Delphi->C#) - 6 votes
Statik ve dinamik metodlarin garip dunyasi - 5 votes
Interface Nedir, Nerelerde ve Neden Kullanırız ? - 5 votes
Meta
Giriş
Yazılar RSS
Yorumlar RSS
WordPress.org
Etiketler-Liste
Absolute API Byte Arrays Class Reference COM CreateDesktop CreateProcess CreateRemoteThread CreateToolHelp32SnapShot DTS EnumDesktopProc EnumDesktops Function Pointer GetCurrentProcess GetIconInfo GetKeyState GetLastInputInfo GetProcessMemoryInfo GetStartupInfo Hacking Inheritance Interface JavaScript Method Pointer Module32First Module32Next OpenDesktop Persistance Pointer Procedure Pointer Process Process32First Process32Next Reqursion RTTI SetProcessWorkingSetSize SQL Server SwitchDesktop TerminateProcess Thread Untyped Parameters VirtualAllocEx VirtualFreeEx WaitForSingleObject WriteProcessMemory