Witam.
Kombinuje i nie wiem jak sobie z tym poradzić aby było prawidłowo. Zacząłem pisać downloader plików z wrzuta.pl.
Póki co jestem na etapie testów pobierania pliku. Do pobierania używam HttpSend z pakietu Synapse. W sumie zapis
by działał, ale dopiero po tym jak ściągnie się całą np mp3ke i dopiero zapisze MemoryStream pod postacią własności
Document do pliku o nazwie pobranej z SaveDialogu. A ja chcę zrobić tak, aby plik był zapisywany na bieżąco na dysku
i zwiększał swój rozmiar w miare zwiększania się postępu pobierania. Tak jak robi to na przykład Opera czy program
USDownloader. Niestety zapisywany plik mp3 zajmuje dwa razy więcej miejsca niż oryginał. I przez połowe jego czasu
trwania zawiera powtarzający się cztero sekundowy kawałek piosenki. A póxniej jeszcze raz cały utwór zapisany w
całości poprawnie. Patrzyłem na ten kod: http://www.delphicorner.f9.co.uk/articles/op12.htm ale on jak dam dla CopyFrom
jako drugi parametr 0 to mam komunikat o błędzie. Poza tym to jest kopiowanie już fizycznie istniejącego pliku w całości,
a ja chcę dopisywać do FileStreama tak aby otrzymać kompletny i poprawny plik mp3 albo też flv. Poniżej fragmenty kodu.
Przykładowa mp3ka to jakiś hiphopolowy syf, ale zajmuje mało i nie trzeba długo czekać na pobranie całości.. Czy zapis
dynamicznie zwiększanego MemoryStreama trzeba rozwiązać w jakiś inny sposób, jeżeli tak to w jaki? Z góry dziękuję.
public
SynHttp : THttpSend;
DirectLink : string;
DnldInProgress : boolean;
DlStream : TFileStream;
end;
TThr = class(TThread)
protected
procedure Execute; override;
end;
var
Form1 : TForm1;
Watek : TThr;
// ... ciach ...
const
ListUrl = 'http://wrzuta.pl/aud/file2/9hk3YQ5Me4/krotki_metraz';
var
I, Pozycja : integer;
Str, Location_Prefix : string;
begin
Screen.Cursor := crHourGlass;
Location_Prefix := 'Location:' +#32;
SynHttp := THttpSend.Create;
SynHttp.Sock.OnStatus := SockCallBack;
// ciach ...
SynHttp.HTTPMethod('GET', ListUrl);
case SynHttp.ResultCode of
302 :
begin
StatusLabel.Caption := 'Przekierowanie do właściwego pliku.';
for I := 0 to SynHttp.Headers.Count -1 do
begin
Str := SynHttp.Headers[I];
Pozycja := Pos(Location_Prefix, Str);
if Pozycja > 0 then
begin
DirectLink := Copy(Str, Pozycja + Length(Location_Prefix), MaxInt);
Break;
end;
end;
ProgressBar.Position := 0;
Watek := TThr.Create(False);
end;
// ... ciach...
procedure TForm1.SockCallBack(Sender: TObject; Reason: THookSocketReason; const Value: string);
begin
if SynHttp.DownloadSize > 0 then
begin
ProgressBar.Max := SynHttp.DownloadSize;
if (Reason = HR_ReadCount) then
begin
ProgressBar.Position := ProgressBar.Position + StrToInt(Value);
StatusLabel.Caption := Format('Pobrano: %d z: %d bajtów',
[ProgressBar.Position, SynHttp.DownloadSize]);
// Tutaj najważniejsze, jak poprawić aby było ok?
DlStream.Position := SynHttp.Document.Size;
DlStream.CopyFrom(SynHttp.Document, 0);
Application.ProcessMessages;
end;
end;
end;
Już sobie poradziłem, nie wiem czy sposób najlepszy ale ważne że działa bez błędów i dla niewielkich
stosunkowo plików z jakimi mamy do czynienienia w przypadku wrzuta.pl prędkościowo też raczej ok:
procedure TMainForm.SockCallBack(Sender: TObject; Reason: THookSocketReason; const Value: string);
begin
if SynHttp.DownloadSize > 0 then
begin
ProgressBar.Max := SynHttp.DownloadSize;
if (Reason = HR_ReadCount) then
begin
ProgressBar.Position := ProgressBar.Position + StrToInt(Value);
StatusLabel.Caption := Format('Pobrano: %d z: %d bajtów',
[ProgressBar.Position, SynHttp.DownloadSize]);
MemStm.Clear;
MemStm.LoadFromStream(SynHttp.Document);
DlStream.Position := MemStm.Position;
DlStream.CopyFrom(MemStm, MemStm.Size);
end;
if SynHttp.Document.Size = SynHttp.DownloadSize then
begin
MemStm.Clear;
MemStm.LoadFromStream(SynHttp.Document);
DlStream.Position := MemStm.Position;
DlStream.CopyFrom(MemStm, MemStm.Size);
MemStm.Free;
DlStream.Free;
end;
end;
end;