-
Привет всем мастерам! Возникла задача скачивания файлов из интернета. Скачал довольно хороший пример.
delphi.int.ru/download/file/257/
но там нет такого нужного момента как докачка файла, при разрыве соединения. Полазил в интернете и нашёл ещё пример
delphisources.ru/pages/sources/internet/2005_year/download_plus.html
но он не компилиться под d7+indy10.1.5 Прошу помочь с этим вопросом. Почитал статьи в интернете, и скачал пару примеров с использованием WinInet.
delphisources.ru/pages/faq/base/download_with_download_again.html
Там используется такой параметр как range, используя его в заголовке idhhtp можно организовать докачку, но тут вопрос метод get при обращении на скачивание файла скидывает в поток поток пишет в файл. Тут просто у меня не понимание - как продолжить дописывать файл при разрыве соединения и организации повторного закачивания?
-
для первого примера - описание delphi.int.ru/articles/39/ Второй пример не компилиться в юните uThreads ругается на строку HTTP.OnWork := OnWork; ошибку выводит: incompatible types: 'Parameters lists differ'Посомтрел в первом примере - там впринципе также работа с onwork происходит... подскажите что может быть не так???
-
скзано же по-русски: incompatible types: 'Parameters lists differ'
текущая версия инди имеет другой список параметров обработчика OnWork по сравнению с компилируемым примером.
-
Список тот же, которые в процедуре обработчика... что в первом примере что во втором
-
хотя не... разница увидена Sender : TObject; и ASender : TObject;
-
Хотя не... всё там также (
-
Нашёл. Поменял. 2-ой пример запустился.
-
только докачка в том понимании в каком она должна быть - не пашет (
-
Список тот же, которые в процедуре обработчика.
Если бы он был тот же, то не было бы incompatible types: 'Parameters lists differ'
-
> Там используется такой параметр как range, используя его > в заголовке idhhtp можно организовать докачку, но тут вопрос > метод get при обращении на скачивание файла скидывает в > поток поток пишет в файл. Тут просто у меня не понимание > - как продолжить дописывать файл при разрыве соединения > и организации повторного закачивания?
Поток, в который скидывают, никуда сам ничего не пишет. Т.ч. надо просто написать часть программы, которая записывает полученные данные в файл на нужное место.
-
TFileStream.Create(ToFolder, fmCreate);
А файл уже есть, допустим часть скачена уже. Не знаю как правильно сделать чтобы поток TFileStream приклеил к уже существующему файлу следющую часть...
думаю сделать так - проверять есть ли файл, если нет - то запрашивать его размер и качать по частям через range, далее эти части "склеивать" между собой. Ну сообствено зная стандартный размер части будет понятно скачалась она полностью или нет, взависимости от этого переходить к скачиванию следующей части.
-
-
1. Запроси размер файла 2. Создай filestream требуемого размера 3. пиши каждую принятую часть в соответствующее место стрима.
PS. из [9] "надо просто написать часть программы, которая записывает полученные данные в файл на нужное место."
-
пока что пытаюсь сделать без потока, просто пробую... натыкаюсь на ряд не понятных моментов. Почему то при докачивании, по идее перемещаю указатель в то место где поток оборвался, но смотрю он увеличивает размер файла ровно в 2 раза... и при скачивании ествсвенно не читабельный... нинаю... как быть Подскажите, где что не так... Думаю может в IdHTTP1.OnWork передвигать указатель tfilestream, но это как то муторно... подскажите плиз. procedure TForm1.Button3Click(Sender: TObject);
var
IdHTTP1:TidHttp;
SourceFileSize: Dword;
FileDate: TDateTime;
SourceFile, SourceURL,FileType: string;
fDownloadStream: TFileStream;
begin
SourceFile:=Edit2.Text;
SourceURL := Edit1.Text;
IdHTTP1:=TIdHTTP.Create(nil);
IdHTTP1.ProtocolVersion := pv1_1;
IdHTTP1.HandleRedirects := True;
IdHTTP1.Head(SourceURL);
SourceFile := IdHTTP1.URL.Document;
SourceFileSize := IdHTTP1.Response.ContentLength;
FileDate := IdHTTP1.Response.LastModified;
FileType := IdHTTP1.Response.ContentType;
if FileExists(IdHTTP1.URL.Document) then
begin
fDownloadStream := TFileStream.Create(SourceFile, fmOpenReadWrite);
Idhttp1.Request.Range:=Format('%d-%d',[fDownloadStream.Position,
SourceFileSize-1]);
fDownloadStream.Seek(SourceFileSize,soFromBeginning);
end
else
begin
fDownloadStream := TFileStream.Create(SourceFile, fmCreate);
fDownloadStream.Seek(0,soFromBeginning); end;
IdHTTP1.Request.ContentType := FileType;
IdHTTP1.Request.ContentRangeStart := fDownloadStream.Position;
IdHTTP1.Request.ContentRangeEnd := SourceFileSize;
IdHTTP1.Get(SourceURL,fDownloadStream);
fDownloadStream.Free;
IdHTTP1.Free;
end;
-
пока разбираюсь пробую без потоков (Tthread).
-
но смотрю он увеличивает размер файла ровно в 2 раза.
один и тот же файл скачан 2 раза. все принятые байты записаны в один и тот же локальный файл.
-
Да я понимаю. но почему он не перемещает указатель потока при помещении в файл. постпенно. а сразу выделет место на диске под весь файл? т.е. грубо говоря, файл не меняетет свой размер он сразу создаётся того размера, который должен быть уже после полного скачивания, но по сути вещей он только начинает его качать. при каждом повторном запуске он опять приклеивает к файлу его размер, и так какждый раз при каждом следующем запуске, хотя реально скачивание только началось... указатель на размер файла вроде почитав про это перемещаю в начало... и при повторном скачивании тоже смотрю сколько скачал, чтоб поставить указатель... fDownloadStream.Seek(SourceFileSize,soFromBeginning);
но почему то этого не происходит (
подскажите как быть ...
-
кто "он"?
и почему "он" должен что-то перемещать? перемещать должен программист.
при каждом повторном запуске он опять приклеивает к файлу его размер
Все в полном соответствии как ты и просил. Локальный файл открыт, указатель смещен в конец. Далее с сервера еще раз запрошен скачиваемый файл. Он благополучно скачивается как и просилось тобой. Все скачанные байты записываются в стрим с текущей позиции указателя.
Все как ты и просил (точнее как ты и запрограммировал).
подскажите как быть ...
и быть или не быть вообще.
-
> vegarulez (27.05.2010 21:07:16) [16]
Это ошибка генофонда, он должен был не увеличивать его, а ставить равным или вообще наращивать по мере необходимости. Пиши своего наследника с исправленым функционалом или переходи на другие компоненты.
-
Медвежонок Пятачок © (27.05.10 22:30) [17]Anatoly Podgoretsky © (28.05.10 07:16) [18]премного благодарен за развёрнутые ответы, и описание личности... а по существу вопроса? Указатель перемещён, всё замечательно - но файл то только начинает скачиваться и я его тут же обрубаю - т.е. грубо говоря скачалось 200 кбайт а на диске уже создан файл в 10 мб. Я вот это не могу понять. Почему создаётся сразу файл размером со скачиваемый файл, когда скачалось всего 200 кб? Локальный файл открыт, указатель смещен в конец.ну как же так? я же его помещаю в начало: fDownloadStream := TFileStream.Create(SourceFile, fmCreate);
fDownloadStream.Seek(0,soFromBeginning); Понимаю, что что-то не до понимаю. Прошу без сарказма указать путь истинный :)
-
> vegarulez (28.05.2010 08:15:19) [19]
Тебе по существу несколько раз объяснили, и не наша проблема, что ты этого не понимаешь.
-
> vegarulez (28.05.2010 08:15:19) [19]
Кстати ты что принял на свой счет, насчет своей личности, случайно не слово ли Генофонд?
-
Anatoly Podgoretsky © (28.05.10 09:01) [21]ну да... были сомнения... Ну всё. Всё получилось. Докачку сделал. определили размер файла и сделал через поток и параметр Request.Range - всё рабит на ура. Теперь вопрос в следующем. Как можно реализовать crc проверку файла? ну т.е. [не знаю как правильно выразиться] допустим есть у меня файл 1.rar, потом появился на его месте новый файл, c тем же названием 1.rar а он допустим не докачался до конца в предыдущий раз, я запускаю программу и она соответсвенно начнёт качать с того байта где была остановлена, но файл то уже совсем другой. Я планирую сделать проверку на размер файла + дата изменения которые получаю перед закачкой. FileDate := IdHTTP1.Response.LastModified;
FileType := IdHTTP1.Response.ContentType; Поэтому вопрос есть ли более элегантный способ, допустим всзять md5 хэш или crc... подскажите как правильно сделать верификацию...
-
> vegarulez (06.06.2010 09:34:22) [22]
Да какая разница, тот или другой файл, все равно качать с последней позиции, а еще лучше с последней позиции минус 1 килобайт. Кроме того, как ты посчитаешь CRC не закачав весь файл?. Но проверять все равно надо, но по известному CRC для проверки целостности файла. Контроль можно сделать и по другому, сначала скачивать рядом лежащий CRC и сравнивать с сохраненым. В качестве CRC принять использовать MD5. Можно также поступать по принципу торрент файлов, когда CRC не один, а множество, по одному CRC на каждый блок фиксированого размера, скажем на каждые 4 кб или более.
-
Заметил, что передаётся параметр ETag, в котором скорее всего содержится crc. Вопрос как оно закодировано? md5?
-
Хотя странно - если бы это был md5 хэш зачем его тогда разделять через чёрточку... подскажите... Date: Sun, 06 Jun 2010 20:01:53 GMT
Server: Apache/2.2.3 (Red Hat)
Last-Modified: Sat, 22 May 2010 09:10:10 GMT
ETag: "293200b-ae3fb0-4872b2cb14080"
Accept-Ranges: bytes
Content-Length: 11419568
Connection: close
Content-Type: text/plain
-
Так... ну вроде понимание про Etag пришло. ETag (Entity tag) является уникальным идентификатором версии объекта и чаще всего генерируется какой-либо хэш-функцией . Спецификация не навязывает каких-либо алгоритмов для вычисления значения ETag — главное чтобы это значение было уникально для всех различных версий одного объекта. Значение ETag одного объекта может совпадать со значением другого, из этого не следует эквивалентность этих объектов. т.е. таким образом не имеет смысла вычисления md5 файла, уже скаченного. проще разруливать, при запросе, по хэшу ETag? В верном направлении мысль пошла?
-
Anatoly Podgoretsky © (06.06.10 09:42) [23] почему лучше минус 1 кб???
-
vegarulez (07.06.10 00:35) [26]
В верном направлении мысль пошла????
vegarulez (07.06.10 06:43) [27] почему лучше минус 1 кб???
-
Удалено модератором
-
Удалено модератором
-
Удалено модератором
-
fDownloadStream := TFileStream.Create(SourceFile, fmCreate);
fDownloadStream.Seek(0,soFromBeginning); вот где собака зарыта. msUpData:=TMemoryStream.Create;
http.Get('http://....ru', msUpData); лучше так.
|