Как загружать через TIdHTTP части с нескольких серверов?

В настоящее время я использую TIdHTTP в Delphi 11 для автоматической загрузки обновлений моего программного обеспечения. Мой установщик относительно большой (около 100 МБ), и загрузка занимает пару минут или даже больше.

Предположим, у меня есть один и тот же установочный файл на разных серверах, есть ли способ использовать все эти серверы для повышения скорости загрузки, что-то вроде Torrent?

Где узкое место? Сервер, который является сервером, — это файл bg или ваш домашний широкополосный доступ. Если это последнее, то все, что вы можете сделать, это улучшить широкополосный доступ. Найдите узкое место.

David Heffernan 30.11.2022 05:09

Можно также запустить несколько загрузок с одного и того же сервера, если он ограничивает пропускную способность только для каждой загрузки, а не для каждого запрашивающего клиента: загружать 3 части параллельно и иметь в 3 раза большую скорость, если у клиента такая большая емкость. Еще почитать: Разница между заголовками Content-Range и Range? и Заголовок диапазона HTTP и Какой диапазон байтов 0- означает и Запрос диапазона HTTP для последнего байта

AmigoJack 30.11.2022 10:17

@DavidHeffernan Узким местом является сервер, потому что это общий сервер, поэтому я хочу попробовать метод «торрент».

delphirules 30.11.2022 12:03
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
108
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Торрент работает, загружая отдельные фрагменты файла из нескольких источников параллельно, а затем объединяя фрагменты в окончательный файл.

Вы можете сделать это и с TIdHTTP, если все серверы (или даже только 1 сервер) поддерживают заголовок HTTP Range request. Так, например, вы можете загрузить файл фрагментами по 1 КБ, загрузив диапазоны байтов 0-1023, 1024-2047, 2048-3071 и так далее до последнего фрагмента.

Если ваши серверы поддерживают это, вы можете сделать следующее:

  1. Создайте файл на диске и предварительно уменьшите его до общего размера конечного файла (см. Как предварительно выделить место для файла в C/C++ в Windows?).
  2. Для каждой части файла, который вы хотите загрузить:
    • Создайте TIdHTTP.
    • Создайте TFileStream1 для конечного файла, запрашивая и предоставляя доступ/права на чтение/запись, а затем ищите его до желаемого начального смещения для фрагмента в файле.
    • Загрузите фрагмент в TFileStream, задав для свойства TIdHTTP.Request.Range значение 'bytes=<start>-<end>', где start — начальное смещение, а end — конечное смещение фрагмента в файле.

1 ОБНОВЛЕНИЕ: О, подождите, я забыл, что TIdHTTP (точнее, TIdIOHandler.ReadStream()) изменяет размер данного TStream до размера загружаемых данных, если этот размер сообщается сервером (что было бы в этой ситуации). Вы НЕ хотите, чтобы это произошло, если вы уже заранее определили размер целевого файла, иначе он будет усечен / поврежден, если вы загрузите несколько TFileStream в один и тот же файл. Таким образом, вы не можете использовать стандартный TFileStream здесь. Однако вы можете создать новый класс из TFileStream и переопределить его виртуальные SetSize() методы, чтобы они ничего не делали. Это должно сработать, я думаю.

В качестве альтернативы:

  1. Для каждой части, которую вы хотите скачать:
    • Создайте TIdHTTP.
    • Создайте TFileStream (здесь подойдет стандартный TFileStream) в отдельный временный файл, запрашивая доступ только для записи и не предоставляя никаких прав, и не ищите его.
    • Загрузите кусок в TFileStream, настроив TIdHTTP.Request.Range как описано выше.
  2. Когда все части будут загружены, создайте новый файл на диске и скопируйте байты каждого временного файла по порядку в этот окончательный файл (см. Как объединить два файла в один?) и удалите временные файлы.

За все годы я никогда не читал и не придумал термин «предварительный размер», чтобы точно описать, что файл должен резервировать больше места, чем он собирается записать в это время (см. Как вы предварительно выделяете место для файла в C /С++ в Windows?)

AmigoJack 30.11.2022 10:26

Ой, подождите, я забыл, что у подхода с предварительным размером возникнут проблемы при использовании стандартного TFileStream. Я обновил свой ответ, чтобы решить эту проблему.

Remy Lebeau 30.11.2022 19:19

Другие вопросы по теме