![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
IDHTTP некорректная докачка файла [D7, WinXP]
Cawa © (2006-11-23 11:30:00)Здравствуйте уважаемые знатоки, у меня возникла следующая проблема.
При закачке нажимаю остановить, после возобновляю докачку. Файл рабочий.
При закачке файла обрываю связь, потом произвожу докачку. Файл нерабочий
Обнаружил следующее, что после обрыва связи в закаченной части файла в конце дописываются некоторое количество нулевых байтов.
Может кто поможет справиться с некорректной докачкой.
Cawa (2006-11-23 15:57:00) [1]2 Warstone ©
Не волнуйся, многопоточность присутствует, просто для сокращения объема выкладываемой информации (с целью её более быстрого усвоения) я нарезал и отредактировал её так, и не заметил WaitFor.
В реалии у меня существует основной поток закачки файла который создает в процессе работы два потока:
1- получающий информацию о закачивающемся файле
2- непосредственно закачивает(TDownloadFile)
и оба этих потока считывают и записывают данные в одном вспомогательном классе.
Так что я искренне извиняюсь если выкладываемые мною исходные тексты, вызвали у кого-нибудь недопонимание!!!
Warstone (2006-11-23 14:40:00) [2]У меня есть небольшой вопрос, а зачем в этом куске
ThreadHttp:=TDownloadFile.Create(true, Data); //Инициализация данных загрузки TotalSize, LoadSize и т.п.
ThreadHttp.Priority:=Priority;
ThreadHttp.Resume;
ThreadHttp.WaitFor;
ThreadHttp.Free; // запись результата загрузки в Data
команда
ThreadHttp.WaitFor;
ведь смысл многопоточности пропадает. Или я чего не знаю о потоках?
Anatoly Podgoretsky (2006-11-23 14:32:00) [3]> Cawa (23.11.2006 14:18:06) [6]
Добавить строчку if LoadSize < 0 then LoadSize = 0;
Cawa (2006-11-23 14:18:00) [4]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
umbra (2006-11-23 14:12:00) [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;
Anatoly Podgoretsky (2006-11-23 12:32:00) [6]> Cawa (23.11.2006 11:32:01) [1]
Попробуй с откатом на несколько килобайт назад, как поступаю все программы подобного рода. Количество килобайт >= размер буфера
umbra (2006-11-23 12:14:00) [7]а останавливаете закачку как?
Cawa (2006-11-23 11:32:00) [8]Вот часть кода модуля по закачке
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:00) [9]часть кода по инициализации закачки (он же и по докачке)
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;