Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2007.06.03;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.48 MB
Время: 0.048 c
15-1178518779
db2admin
2007-05-07 10:19
2007.06.03
Модульное ПО


11-1161100472
Sapersky
2006-10-17 19:54
2007.06.03
OnEndEditLVItem


2-1179162994
Просто_новичок
2007-05-14 21:16
2007.06.03
Запись в фал значений из динамического массива


15-1176923405
Чапаев
2007-04-18 23:10
2007.06.03
гы-гы-гымн свободному ПО


15-1178174073
clickmaker
2007-05-03 10:34
2007.06.03
Как запретить сохранение ссылок на Web Folders?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский