Конференция "Сети" » Как можно реализовать многосекционную закачку файла по http?
 
  • Usov © (27.01.09 17:24) [0]
    Как можно реализовать многосекционную закачку файла по http протоколу?
  • Palladin © (27.01.09 18:47) [1]
    Его изучив. В лице поля заголовка Range.
  • Usov © (27.01.09 22:33) [2]
    А если по простому, можно ли это сделать с помощью TidHTTP (Indy) или THTTPCli (ICS)?
  • Palladin © (28.01.09 13:39) [3]
    У TIdHTTP есть соотвествующие свойства.
  • Usov © (28.01.09 19:54) [4]

    > У TIdHTTP есть соотвествующие свойства.

    Это все понятно, но как организовать несколько одновременных скачек и чтоб это все писать в один файл?
  • Медвежонок Пятачок © (28.01.09 21:25) [5]
    несколько idhttp
  • Usov © (29.01.09 10:25) [6]
    Насколько я понял многие знают ответ но неохотно делятся им:)
    Полазил немного по инету, поковырял библиотеку ICS, и пришел к выводу:
    для мультисекционной закачки необходимо:
    1) открыть файл на диске (TFileStream)
    2) создать массив с TidHTTP (количество их равно количеству секций)
    3) каждому элементу TidHTTP в свойстве .Reques.Range или .Reques.ContentRangeStart и .Reques.ContentRangeEnd (еще не разобрался) присваиваем этим свойствам соответствующие сегменты файла
    4) каждый элемент TidHTTP придется запускать в отдельном потоке
    тут напрашивается вопрос при срыве закачки как определить какой сегмент насколько закачан, при одной секции все понятно, а как быть если секций 5?
  • Медвежонок Пятачок © (29.01.09 10:52) [7]
    тут напрашивается вопрос при срыве закачки как определить какой сегмент насколько закачан, при одной секции все понятно, а как быть если секций 5?

    запоздалый вопрос.
    при срыве закачки уже поздняк метаться.
    еще при старте потоков, каждый должен знать откуда и докуда ему следует запрашивать рейндж.
  • Anatoly Podgoretsky © (29.01.09 11:36) [8]
    > Usov  (29.01.2009 10:25:06)  [6]

    Все, кроме пункта 4, для ICS потоки не нужны, так как он поддерживает событийную модель.
  • tesseract © (29.01.09 11:53) [9]

    > при одной секции все понятно, а как быть если секций 5?


    Читать из файла в которой закачиваешь.


    > Все, кроме пункта 4, для ICS потоки не нужны,


    Да они и ведут себя в потоке не всегда предсказуемо.
  • Anatoly Podgoretsky © (29.01.09 12:02) [10]
    > tesseract  (29.01.2009 11:53:09)  [9]

    > Да они и ведут себя в потоке не всегда предсказуемо.

    У многих такое c потоками даже без использования ICS
  • Usov © (29.01.09 13:02) [11]
    Реализация на ICS не интересует так как там это уже все есть компонент TMultipartHttpDownloader но .
    Интересна реализация на TidHTTP. Я помоему врубился в технологию но не могу сообразить как реализовать дозакачку при использовании нескольких секций. Может как то пробежаться по файлу и определить где в файле есть данные а где нет, ведь писать то каждую секцию буду в определенное место?
  • Медвежонок Пятачок © (29.01.09 13:08) [12]
    так как там это уже все есть компонент TMultipartHttpDownloader но .

    А какое он имеет отношение с сабжу?

    Может как то пробежаться по файлу и определить где в файле есть данные а где нет, ведь писать то каждую секцию буду в определенное место?

    Когда стартует первая закачка, то никакого файла еще нет.
    А рэйндж уже пора указывать.
    А указав рейндж для потока, надо его запомнить, чтобы потом не ворзникало мыслей "по файлу бегать"
  • Usov © (29.01.09 13:21) [13]

    > Когда стартует первая закачка, то никакого файла еще нет.
    > А рэйндж уже пора указывать.
    > А указав рейндж для потока, надо его запомнить, чтобы потом не ворзникало мыслей "по файлу бегать"

    Как это файла нет, будем качать в память?
    Рейндж я согласен указывать обязательно до GET запрса надо, но в параметрах GET я указываю куда idhttp будет складывать полученные данные, то есть TFileStrim.
  • Медвежонок Пятачок © (29.01.09 13:27) [14]
    Как это файла нет, будем качать в память?

    Он у тебя появлется еще до того, как запрос на файл на сервер уйдет?
  • Медвежонок Пятачок © (29.01.09 13:32) [15]
    выполнил первый запрос "head", получил размер ресурса.
    создал локальный файл указанного размера.
    поделил рамер на количество секций, определил границы секций.
    создал потоки, сказал им откуда качать, сколько качать, и начиная откуда качать.
    все!
    поток знает откуда брать данные и куда их складывать.
  • Usov © (29.01.09 13:33) [16]

    > Он у тебя появлется еще до того, как запрос на файл на сервер
    > уйдет?

    Фактически да

    var
     fs: TFileStream;
    begin
     fs := TFileStream.Create('c:\test.avi', fmCreate);
     ...
     колдуем с ранджем
     ...
     idHTTP.Get('http://anysite.com/test.avi', fs);
    end
  • Usov © (29.01.09 13:36) [17]

    > выполнил первый запрос "head", получил размер ресурса.
    > создал локальный файл указанного размера.
    > поделил рамер на количество секций, определил границы секций.
    >
    > создал потоки, сказал им откуда качать, сколько качать,
    > и начиная откуда качать.
    > все!
    > поток знает откуда брать данные и куда их складывать.

    Насколько я понимаю то все потоки должны работать с единым указателем на файл?
  • Медвежонок Пятачок © (29.01.09 13:40) [18]
    то все потоки должны работать с единым указателем на файл?

    зависит от личных политических взглядов.
    могут и с одним, а могут и с отдельными темповыми файлами.
  • Anatoly Podgoretsky © (29.01.09 13:51) [19]
    > Usov  (29.01.2009 13:02:11)  [11]

    Дозакачку должен обеспечивать сервер, ему только надо сообщить какой диапазон существует.
  • Usov © (29.01.09 14:10) [20]
    Насколько я понял, то если указать рейндж например 100-500, то компонет idHTTP запишет соответствено скачаное в файл с позиции 100 и по 500?
    Получается для того чтоб дозакачать прерванную закачку надо:
    или где то хранить информацию о количестве сегментов и начало и конец каждого сегмента для каждой закачки
    или просматривать каким то образом файл для определения количества скачанных кусков.
  • Медвежонок Пятачок © (29.01.09 14:14) [21]
    то компонет idHTTP запишет соответствено скачаное в файл с позиции 100 и по 500?

    Он ничего не знает ни про какие такие "позиции"
  • Медвежонок Пятачок © (29.01.09 14:24) [22]
    idHTTP запишет соответствено скачаное в файл с позиции 100 и по 500?

    с какого перепугу?
    он запишет скачиваемое либо по указанному адресу буфера, начиная с его начала, либо в текущую позицию потока, если в метод был передан поток.

    но никак не с позиции 100, даже если это значение было в заголовке запроса.
  • Usov © (29.01.09 14:38) [23]
    может у кого есть пример?
  • Медвежонок Пятачок © (29.01.09 14:42) [24]
    пример чего?
    трех арифметических операций сложения вычитания и деления?
  • Anatoly Podgoretsky © (29.01.09 16:11) [25]

    > Насколько я понял, то если указать рейндж например 100-500,
    >  то компонет idHTTP запишет соответствено скачаное в файл
    > с позиции 100 и по 500?

    Разве он пишет в файл?
  • Usov © (29.01.09 16:56) [26]

    > Разве он пишет в файл?

    А куда если не в файл? можно конечно в TMemoryStream но ну его нафиг держать в памяти 4 гиговый файл.
  • Медвежонок Пятачок © (29.01.09 16:58) [27]
    Он пишет в стрим, а не в файл.
  • Usov © (29.01.09 17:00) [28]
    Попытаюсь обобщить услышанное:
    Задача закачать файл 100 байт в две секции в один файл (не создаем несколько временных).
    1) получаем заголовок запроса для определения размера файла
    2) создаем файловый поток для файла
    3) создаем первый поток для idhttp где устнавливаем рендж с 0 по 50
    4) устанавливаем позицию записи в файл в начало (необязательно)
    5) делаем гет запрос
    6) создаем второй поток для idhttp где устнавливаем рендж с 51 до 100
    7) устанавливаем позицию записи с 51 байта
    8) делаем гет запрос

    пункты 4 и 7 под сомнением так как неизвестно как поведет себя запись при одновременном обращении двух потоков к одному файлу.

    жду комментов и предложений
  • Медвежонок Пятачок © (29.01.09 17:08) [29]
    так как неизвестно как поведет себя запись при одновременном обращении двух потоков к одному файлу

    кому неизвестно?
  • Usov © (29.01.09 17:16) [30]

    > кому неизвестно?

    конечно же мне:)
  • FireMan_Alexey (03.02.09 14:32) [31]
    Если компонент пишет в стрим у тебя есть размер записанного!!!
    Создай 5 Мем стримов и призакачке проверяй на заполнение скажем по 128Кб и по заполнению кидай их на винт :)
  • FireMan_Alexey (03.02.09 14:34) [32]
    А когда закачка разрывается, в стриме есть позиция откуда качать дальше называется TMemoryStream.SIZE :)
  • Usov © (04.02.09 14:20) [33]

    > А когда закачка разрывается, в стриме есть позиция откуда
    > качать дальше называется TMemoryStream.SIZE :)

    Это ясно, а как определить после аварийной перезагрузки программы сколько секций было в закачке и сколько закачано в каждой сессии? Получается надо где-то хранить отдельно информацию о количестве и начале и объеме каждой секции.
  • Anatoly Podgoretsky © (04.02.09 14:40) [34]
    > Usov  (04.02.2009 14:20:33)  [33]

    Получается так
  • Медвежонок Пятачок © (04.02.09 14:42) [35]
    Это ясно, а как определить после аварийной перезагрузки программы сколько секций было в закачке и сколько закачано в каждой сессии? Получается надо где-то хранить отдельно информацию о количестве и начале и объеме каждой секции.

    ну ты догада.
  • FireMan_Alexey (04.02.09 15:28) [36]
    А у Download Master-a еще файл *.dfmr есть :)
  • Anatoly Podgoretsky © (04.02.09 16:19) [37]
    > Медвежонок Пятачок  (04.02.2009 14:42:35)  [35]

    Так созранять надо эту информацию
  • Usov © (04.02.09 23:56) [38]

    > А у Download Master-a еще файл *.dfmr есть :)

    Насколько я знаю, DM пишет инфу о секциях в конец того файла что закачивает.
  • FireMan_Alexey (05.02.09 03:38) [39]
    Сейчас нет
    А раньше был :), я по старой памяти :)
  • KSergey © (10.02.09 11:55) [40]
    > Usov ©   (04.02.09 23:56) [38]
    > Насколько я знаю, DM пишет инфу о секциях в конец того файла что закачивает.

    Хм, ну тоже прикольно придумано. Потом подрубить файл - и все. Чистенько и "ничего лишнего".
  • Usov © (10.02.09 15:26) [41]

    > Хм, ну тоже прикольно придумано. Потом подрубить файл -
    > и все. Чистенько и "ничего лишнего".

    Только если сорвется на последних байтах закачка - хана всему файлу.
  • FireMan_Alexey © (11.02.09 00:35) [42]

    > Только если сорвется на последних байтах закачка - хана
    > всему файлу.


    В смысле?
    Докачаеш :)
    Ты же для этого и секции вводиш.
  • Usov © (11.02.09 18:02) [43]

    > > Только если сорвется на последних байтах закачка - хана
    > > всему файлу.
    >
    >
    > В смысле?
    > Докачаеш :)
    > Ты же для этого и секции вводиш.
    >

    Всмысле если хранить инфу о секциях в конце файла.
  • FireMan_Alexey © (11.02.09 21:42) [44]
    Сделай Head, получи размер, зарезервируй место на диске и вперед :)
    А информацию можеш хранить вконце файла.
    А если даже и двигать, то информацию можно достать размер файла - размер блока параметров секций.
  • leonidus (25.10.09 21:44) [45]
    Удалено модератором
    Примечание: СПАМ
  • sniknik © (26.10.09 01:19) [46]
    > Господа знатоки ICS
    нфига быть знатоком, нужно просто читать внмательней

    > Реализация на ICS не интересует так как там это уже все есть компонент TMultipartHttpDownloader

    или дело принципа? ну так посмотри в исходники.
  • brother © (26.10.09 09:33) [47]
    > sniknik ©   (26.10.09 01:19)

    ты на дату сабжа смотрел? ;)
  • sniknik © (26.10.09 21:47) [48]
    > ты на дату сабжа смотрел? ;)
    а ты смотрел на дату поста на который у меня ответ?
  • Usov © (28.10.09 18:03) [49]
    тема актуальна еще, просто руки никак не доходят заняться реализацией.
  • Дмитрий Белькевич (29.10.09 18:12) [50]
    >Может как то пробежаться по файлу и определить где в файле есть данные а где нет, ведь писать то каждую секцию буду в определенное место?

    1. Создавать файл в каком-то своём формате, после полного приёма пересобирать файл.
    2. Создавать дополнительный файл с указанием что скачалось или что не скачалось.
    3. Запоминать данные о закачках в базе данных.
    4. Запоминать данные о закачках в реестре.

    Выбирай.
 
Конференция "Сети" » Как можно реализовать многосекционную закачку файла по http?
Есть новые Нет новых   [134437   +30][b:0][p:0.001]