ต้องการตัวอย่าง Delphi 6 เพื่ออัปเดตแถบความคืบหน้าระหว่างการดำเนินการส่ง TIdSmtp โดยเฉพาะอย่างยิ่งสำหรับไฟล์แนบขนาดใหญ่

ฉันใช้องค์ประกอบ Indy TIdSmtp เพื่อส่งอีเมล อีเมลที่ฉันส่งจะมีไฟล์แนบขนาดใหญ่ โดยปกติจะมีขนาดตั้งแต่ 5 ถึง 40 MB ฉันต้องการอัปเดตแถบความคืบหน้าที่จะแสดงความคืบหน้าโดยรวมของการส่งเป็นเปอร์เซ็นต์ของจำนวนไบต์ทั้งหมดที่ต้องส่ง ฉันไม่สนหรอกว่าจะแม่นยำแค่ไหน แค่ดีพอที่จะให้คนที่ดูแถบความคืบหน้าทราบว่ากระบวนการส่งอีเมลโดยรวมนั้นไปไกลแค่ไหนแล้ว

ใครสามารถชี้ให้ฉันดูตัวอย่างโค้ดที่แสดงวิธีการทำเช่นนี้ได้หรือไม่


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
เพื่อลดค่าใช้จ่ายในการเข้ารหัสสตรีมชั่วคราว คุณสามารถใช้คลาส TIdDiscardStream หรือ TIdEventStream สาธารณะของ Indy หรือคัดลอกการใช้งานคลาส TIdCalculateSizeStream ส่วนตัวของ Indy จากหน่วย IdMulipartFormData.pas ด้วยวิธีนี้ จะไม่มีการจัดเก็บข้อมูลไว้ในหน่วยความจำ แต่คุณยังสามารถนับจำนวนไบต์ที่เขียนลงในสตรีมได้ - person Remy Lebeau; 16.05.2012