Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.06.03;
Скачать: CL | DM;

Вниз

IDHTTP некорректная докачка файла   Найти похожие ветки 

 
Cawa ©   (2006-11-23 11:30) [0]

Здравствуйте уважаемые знатоки, у меня возникла следующая проблема.
При закачке нажимаю остановить, после возобновляю докачку. Файл рабочий.
При закачке файла обрываю связь, потом произвожу докачку. Файл нерабочий

Обнаружил следующее, что после обрыва связи в закаченной части файла в конце дописываются некоторое количество нулевых байтов.

Может кто поможет справиться с некорректной докачкой.


 
Cawa ©   (2006-11-23 11:32) [1]

Вот часть кода модуля по закачке

TDownloadStatus = (dsReady, dsError, dsLoad, dsLoading, dsStoped, dsDelete, dsDeleted);

TDownloadFile = class(TThread)
 public
   URL: String;
   FileName: String;
   Directory: String;
   TotalSize: Integer;
   LoadSize: Integer;
   Status: TDownloadStatus;
   ErrorText: String;
 … … …
 private
   StartSize : Integer;
   HTTP      : TIdHTTP;
   procedure OnWork(Sender : TObject; AWorkMode : TWorkMode; const AWorkCount : Integer);
   procedure OnWorkBegin(Sender : TObject; AWorkMode : TWorkMode; const AWorkCountMax : Integer);
   procedure OnWorkEnd(Sender: TObject; AWorkMode: TWorkMode);
 protected
   procedure Execute; override;
end;

////////////////////////////////////////////////////////////////////////////////

procedure TDownloadFile.Execute;
var
 FileStream : TFileStream;
begin
 HTTP := TIdHTTP.Create(nil);
 if FileExists(Directory + "\" + FileName) then
 begin
   FileStream := TFileStream.Create(Directory + "\" + FileName, fmOpenReadWrite);
   //FileStream.Position := FileStream.Size;
   FileStream.Position:=LoadSize;
 end else
 begin
   FileStream := TFileStream.Create(Directory + "\" + FileName, fmCreate);
 end;
 HTTP.OnWork := OnWork;
 HTTP.OnWorkBegin := OnWorkBegin;
 HTTP.OnWorkEnd := OnWorkEnd;
 HTTP.Request.ContentRangeStart :=LoadSize;
 HTTP.Request.ContentRangeEnd := TotalSize;

… // настройки соединения proxy redirect и т.д. …

 StartSize := LoadSize;
 try
   HTTP.Get(URL, FileStream);
 except
   on E : Exception do
   begin
     Status := dsError;
     ErrorText := E.Message;
     MessageBox(Application.Handle, PChar("Ошибка при загрузке файла." + #13#10 + E.Message), PChar(Options.Name), MB_OK or MB_ICONERROR);
   end;
 end;

 HTTP.Free;
 FileStream.Free;

End;

////////////////////////////////////////////////////////////////////////////////

procedure TDownloadFile.OnWork(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer);
begin
 if AWorkMode = wmRead then
 begin
   LoadSize := StartSize + AWorkCount;
 end;
 if Status = dsStoped then HTTP.Disconnect;
end;

////////////////////////////////////////////////////////////////////////////////

procedure TDownloadFile.OnWorkBegin(Sender : TObject; AWorkMode : TWorkMode; const AWorkCountMax : Integer);
begin
 Status := dsLoading; // начало загрузки
end;


 
Cawa ©   (2006-11-23 11:32) [2]

часть кода по инициализации закачки (он же и по докачке)

var
 HTTP : TIdHTTP;
 ThreadHttp:TDownloadFile;
begin
 HTTP := TIdHTTP.Create(nil);
 try
   HTTP.Head(Data.URL);
   Data.Status:= dsReady;
   Data.ErrorText := "Ошибок нет";
   Data.TotalSize := HTTP.Response.ContentLength;
 except
   on E : Exception do
   begin
     Data.Status := dsError;
     Data.ErrorText := E.Message;
     Data.TotalSize := 0;
     MessageBox(Application.Handle, PChar("Ошибка при загрузке файла." + #13#10 + E.Message), PChar(Options.Name), MB_OK or MB_ICONERROR);
   end;
 end;
 HTTP.Free;
If Data.Status<>dsError then
begin
  ThreadHttp:=TDownloadFile.Create(true, Data); //Инициализация данных загрузки TotalSize, LoadSize и т.п.
  ThreadHttp.Priority:=Priority;
  ThreadHttp.Resume;
  ThreadHttp.WaitFor;
  ThreadHttp.Free; // запись результата загрузки в Data
End;


 
umbra ©   (2006-11-23 12:14) [3]

а останавливаете закачку как?


 
Anatoly Podgoretsky ©   (2006-11-23 12:32) [4]

> Cawa  (23.11.2006 11:32:01)  [1]

Попробуй с откатом на несколько килобайт назад, как поступаю все программы подобного рода. Количество килобайт >= размер буфера


 
umbra ©   (2006-11-23 14:12) [5]

в принципе можно запрашивать файл по кускам в промежуточный поток, а в скачанный файл дописывать только когда получен блок нужного размера. Наподобие


const
  ChunkSize = 4096;


procedure TDownloadFile.Execute;
var
FileStream : TFileStream;
TmpStream: TMemoryStream;
begin
HTTP := TIdHTTP.Create(nil);
if FileExists(Directory + "\" + FileName) then
begin
  FileStream := TFileStream.Create(Directory + "\" + FileName, fmOpenReadWrite);
  //FileStream.Position := FileStream.Size;
  FileStream.Position:=LoadSize;
end else
begin
  FileStream := TFileStream.Create(Directory + "\" + FileName, fmCreate);
end;
TmpStream := TMemoryStream.Create;

while FileStream.Size < TotalSize do
begin
 TmpStream.Position := 0;
 HTTP.Request.ContentRangeStart := FileStream.Size;
 if TotalSize - FileStream.Size >= ChunkSize then
   HTTP.Request.ContentRangeEnd := FileStream.Size + ChunkSize
 else
   HTTP.Request.ContentRangeEnd := TotalSize;
 try
   HTTP.Get(URL, TmpStream);
 except
   on E : Exception do
     begin
       TmpStream.SetSize(0);
       {.........................................}
     end;
end;
if TmpStream.Size > 0 then
   FileStream.CopyFrom(TmpStream, 0);

end;

HTTP.Free;
tmpstream.Free;
FileStream.Free;

End;


 
Cawa ©   (2006-11-23 14:18) [6]

2 umbra © - устанавливал значение status:=dsStop;
2 Anatoly Podgoretsky - Огромное спасибо откат помог, и как я сам не догадался?!!
2 Всех остальных - ниже привожу сделанное изменение, мало ли кому нужно осуществлять докачку


procedure TDownloadFile.Execute;
var
FileStream : TFileStream;
begin
HTTP := TIdHTTP.Create(nil);
LoadSize:=Loadsize-HTTP.RecvBufferSize; // исправление здесь :))
if FileExists(Directory + "\" + FileName) then


 
Anatoly Podgoretsky ©   (2006-11-23 14:32) [7]

> Cawa  (23.11.2006 14:18:06)  [6]

Добавить строчку if LoadSize < 0 then LoadSize = 0;


 
Warstone ©   (2006-11-23 14:40) [8]

У меня есть небольшой вопрос, а зачем в этом куске
ThreadHttp:=TDownloadFile.Create(true, Data); //Инициализация данных загрузки TotalSize, LoadSize и т.п.
 ThreadHttp.Priority:=Priority;
 ThreadHttp.Resume;
 ThreadHttp.WaitFor;
 ThreadHttp.Free; // запись результата загрузки в Data

команда

 ThreadHttp.WaitFor;

ведь смысл многопоточности пропадает. Или я чего не знаю о потоках?


 
Cawa ©   (2006-11-23 15:57) [9]

2 Warstone ©
Не волнуйся, многопоточность присутствует, просто для сокращения объема выкладываемой информации (с целью её более быстрого усвоения) я нарезал и отредактировал её так, и не заметил WaitFor.
В реалии у меня существует основной поток закачки файла который создает в процессе работы два потока:
1- получающий информацию о закачивающемся файле
2- непосредственно закачивает(TDownloadFile)
и оба этих потока считывают и записывают данные в одном вспомогательном классе.
Так что я искренне извиняюсь если выкладываемые мною исходные тексты, вызвали у кого-нибудь недопонимание!!!



Страницы: 1 вся ветка

Текущий архив: 2007.06.03;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.062 c
15-1178168718
Рауф
2007-05-03 09:05
2007.06.03
Перенос БД Paradox на другую машину.


3-1173938073
In/Out
2007-03-15 08:54
2007.06.03
Запрос SQL


1-1175750114
s_
2007-04-05 09:15
2007.06.03
Exe как Dll


15-1178712342
syte_ser78
2007-05-09 16:05
2007.06.03
Вопрос к знатокам сопромата


2-1179043036
Calibr
2007-05-13 11:57
2007.06.03
Заставка с параметрами