Нужен пример Delphi 6 для обновления индикатора выполнения во время операции отправки TIdSmtp, особенно для больших вложений

Я использую компонент Indy TIdSmtp для отправки электронной почты. К электронным письмам, которые я отправляю, будут прикреплены большие вложения, обычно размером от 5 до 40 МБ. Я хочу обновить индикатор выполнения, который будет показывать общий ход отправки в процентах от общего количества байтов, которые необходимо отправить. Меня не волнует, действительно ли это точно, просто достаточно, чтобы дать кому-то, наблюдающему за индикатором выполнения, указание, насколько далеко продвинулся общий процесс отправки электронной почты.

Может ли кто-нибудь указать мне на образец кода, который показывает мне, как это сделать?


person Robert Oschler    schedule 16.05.2012    source источник


Ответы (1)


TIdSMTP кодирует электронное письмо на лету, когда оно отправляется на сервер. Общее количество отправляемых байтов заранее неизвестно. Единственный способ определить значение, даже достаточно близкое, - это закодировать электронное письмо во временный TStream с помощью метода TIdMessage.SaveToStream(), а затем получить значение свойства TStream.Size. Поскольку вы кодируете большие вложения, это займет некоторое время и потребует больших затрат памяти. Поскольку TIdSMTP просто повторно перекодирует электронное письмо во время передачи, нет никакой гарантии, что количество фактически переданных байтов будет соответствовать временному интервалу TStream.Size из-за динамического характера различных заголовков электронной почты, таких как временные метки и границы MIME.

Чтобы определить, сколько байтов фактически отправлено, используйте события TIdSMTP.OnWork..., где для параметра AWorkMode будет установлено значение wmWrite. Поскольку TIdSMTP.Send() не знает заранее, сколько байтов оно будет отправлено, параметр AWorkCountMax события TIdSMTP.OnWorkBegin будет 0, но, по крайней мере, вы будете знать, когда фактические данные электронной почты начнут кодироваться / отправляться (после того, как TIdSMTP обменялся несколькими командами с сервер). Параметр AWorkCount события TIdSMTP.OnWork будет общим количеством фактически отправленных байтов. Когда запускается событие TIdSMTP.OnWorkEnd, отправка электронного письма завершена.

На основе свойства temp TStream.Size и параметра AWorkCount события TIdSMTP.OnWork вы сможете отображать приблизительный процент для индикатора выполнения. Точность на 100% не будет гарантирована, но она будет близкой.

person Remy Lebeau    schedule 16.05.2012
comment
Спасибо. Вот что мне было нужно. Все лучше, чем компьютер, который кажется зависшим на чрезмерно долгое время. По крайней мере, мои пользователи будут видеть, что индикатор выполнения что-то делает, чтобы они знали, что мое приложение не заблокировано. Даже если я сделаю что-то крайне неточное, например умножу общий размер вложений на 2 и разделю его на AWorkCount, чтобы получить процент, по крайней мере, будет некоторая визуальная обратная связь. - person Robert Oschler; 16.05.2012
comment
Чтобы минимизировать накладные расходы на кодирование временного потока, вы можете использовать общедоступный класс Indy TIdDiscardStream или TIdEventStream или скопировать реализацию частного класса TIdCalculateSizeStream Indy из модуля IdMulipartFormData.pas. Таким образом, данные не сохраняются в памяти, но вы все равно можете подсчитать, сколько байтов записано в поток. - person Remy Lebeau; 16.05.2012