Форум: "Сети";
Текущий архив: 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