บทความนี้แนะนำวิธีการใช้ไลบรารีที่มีอยู่ใน Java เพื่อเขียนรหัสไคลเอนต์ FTP และพัฒนาเป็นตัวควบคุมแอปเพล็ตเพื่อสร้างแบตช์ไฟล์ขนาดใหญ่อัปโหลดและดาวน์โหลดตัวควบคุมตามเว็บ จากชุดของไลบรารีลูกค้า FTP บทความนี้ให้คำอธิบายโดยละเอียดและการใช้งานรหัสในหนึ่งในไลบรารี J-FTP ที่มีประสิทธิภาพมากขึ้นเช่นแถบความคืบหน้าการต่อเนื่องเบรกพอยต์การทำแผนที่ของเครือข่ายภายในและภายนอก หวังว่าบทความนี้จะมีบทบาทในการดึงดูดหยก
1. บทนำ
ในระหว่างการใช้งานโครงการข้อกำหนดการอัปโหลดและดาวน์โหลดไฟล์บนเว็บได้เกิดขึ้นแล้ว ผู้ใช้ทั่วทั้งจังหวัด (หรือทั่วประเทศ) จำเป็นต้องอัปโหลดไฟล์บางไฟล์ไปยังเซิร์ฟเวอร์ไฟล์ในศูนย์ที่แน่นอน เอกสารเหล่านี้ใช้สำหรับการก่อสร้างทางวิศวกรรมขนาดใหญ่ซึ่งอาจเกี่ยวข้องกับโครงการก่อสร้างมูลค่าหลายสิบล้านหรือหลายร้อยล้านหยวน ไฟล์มีสามลักษณะที่แตกต่างกัน: หนึ่งคือไฟล์มีขนาดใหญ่ซึ่งอาจถึง 50m; ประการที่สองคือจำนวนไฟล์มีขนาดใหญ่ซึ่งอาจประมาณ 15; ประการที่สามคือจำเป็นต้องมีลายเซ็นดิจิตอลและการเข้ารหัสข้อมูลในแง่ของความปลอดภัยของข้อมูล
ก่อนอื่นให้พิจารณาวิธีการส่งผ่าน HTTP อย่างไรก็ตามจากการเปรียบเทียบฉันพบอย่างรวดเร็วว่าความต้องการข้างต้นได้รับการตอบสนอง:
1: การอัปโหลดโดยใช้โปรโตคอล HTTP ดูเหมือนจะเหมาะกว่าสำหรับความสะดวกในการเขียนโปรแกรมเว็บ การอัปโหลดไฟล์น้อยกว่า 1M นั้นเร็วกว่าการอัปโหลดไฟล์เล็กน้อยโดยใช้โปรโตคอล FTP แต่อาจไม่มีอะไรทำเกี่ยวกับการถ่ายโอนแบทช์และไฟล์ขนาดใหญ่ แน่นอนว่ามันยังมีข้อได้เปรียบเช่น FTP ไม่จำเป็นต้องเริ่มบริการ FTP ทางฝั่งเซิร์ฟเวอร์
2: การอัปโหลดไฟล์ที่มีไฟล์ที่มีขนาดใหญ่กว่า 1M โดยใช้โปรโตคอล FTP นั้นเร็วกว่า HTTP ยิ่งไฟล์มีขนาดใหญ่ขึ้นความเร็วในการอัปโหลดจะเร็วกว่าความเร็วในการอัปโหลด HTTP หลายเท่า และเขียนโปรแกรมใน Java; FTP สะดวกกว่า HTTP
ผู้เขียนเคยใช้ VB และเขียนการควบคุม ActiveX เพื่ออัปโหลดและดาวน์โหลดไฟล์แบตช์และฟังก์ชั่นของมันก็มีประสิทธิภาพมากเช่นกัน เป็นเพียงว่าเนื่องจากไม่มีลายเซ็นดิจิตอลพิเศษสำหรับไฟล์ CAB หรือ OCX จึงจำเป็นต้องทำการตั้งค่าที่น่าเบื่อสำหรับลูกค้าเช่นการตั้งค่าไซต์ที่ปลอดภัยลดระดับความปลอดภัยของลูกค้า ฯลฯ โซลูชั่นบางอย่างถูกยกเลิก
ในเวลาเดียวกันเมื่อพิจารณาว่าไฟล์จะต้องมีการลงนามและเข้ารหัสแบบดิจิทัลบนไคลเอนต์มันก็ตัดสินใจใช้แอปเพล็ตเพื่อใช้งาน - ก่อนที่จะอัปโหลดไฟล์ข้อมูลคีย์ USBKEY ท้องถิ่นสามารถรับได้จากไคลเอนต์เพื่อดำเนินการเข้ารหัสและการประมวลผลลายเซ็นของไฟล์ที่อัปโหลด แม้ว่าการใช้แอปเพล็ตจะต้องมีการติดตั้งสภาพแวดล้อม JRE Runtime บนไคลเอนต์ซึ่งนำมาซึ่งความไม่สะดวกในการจัดการและการใช้งานไคลเอนต์ แต่อาจเป็นราคาที่ค่อนข้างเล็กในการเปรียบเทียบความปลอดภัยของไฟล์และไฟล์จำนวนมาก
เพื่อสรุปสภาพแวดล้อมการดำเนินงาน:
FTP Server Side: Serv-U, โปรแกรม Servent Server Professional มีการดาวน์โหลดซอฟต์แวร์สำเร็จรูปบนอินเทอร์เน็ตแน่นอนว่าผู้อ่านอาจเขียนโปรแกรมการรับไฟล์ FTP ฝั่งเซิร์ฟเวอร์เพื่ออธิบาย หากไม่มีข้อกำหนดหรือฟังก์ชั่นพิเศษ Serv-U ควรจะสามารถตอบสนองความต้องการอัพโหลดและดาวน์โหลดทั่วไปของเราได้
ไคลเอนต์: Java Applet เทคโนโลยีที่ทำให้ Java ได้รับความนิยมกลับมาแล้วอ้างว่าเปรียบได้กับ ActiveX ของ Microsoft แน่นอนตอนนี้ Java มี Java FX มันเป็นเครื่องทดแทนแอปเพล็ตหรือไม่?
สภาพแวดล้อมแอปพลิเคชัน: อินเทอร์เน็ตวัตถุประสงค์สูงสุด
2. ตัวเลือกของไลบรารีไคลเอนต์ Java FTP
ลองจินตนาการถึงสถานการณ์ - เราต้องการเขียนแอปพลิเคชัน Java บริสุทธิ์ที่อัปโหลดและดาวน์โหลดไฟล์จากเซิร์ฟเวอร์ FTP ที่ทำงานบนคอมพิวเตอร์ระยะไกล นอกจากนี้เรายังต้องการรับข้อมูลไฟล์พื้นฐานสำหรับไฟล์ระยะไกลเหล่านั้นสำหรับการดาวน์โหลดเช่นชื่อไฟล์ข้อมูลหรือขนาดไฟล์
ในขณะที่มันเป็นไปได้และอาจน่าสนใจในการเขียนตัวจัดการโปรโตคอล FTP ตั้งแต่เริ่มต้นงานก็ยากและอาจเป็นอันตราย เนื่องจากเราไม่เต็มใจที่จะใช้เวลาพลังงานหรือเงินในการเขียนโปรแกรมการประมวลผลเองเราจึงหันไปใช้ส่วนประกอบที่นำมาใช้ซ้ำได้ซึ่งมีอยู่แล้ว และห้องสมุดจำนวนมากมีให้บริการออนไลน์
การค้นหาไลบรารีไคลเอนต์ Java FTP ที่ยอดเยี่ยมที่เหมาะสมกับความต้องการของเรานั้นไม่ง่ายอย่างที่คิด ในทางตรงกันข้ามนี่เป็นงานที่เจ็บปวดและซับซ้อนมาก ก่อนอื่นต้องใช้เวลาพอสมควรในการค้นหาไลบรารีไคลเอนต์ FTP ประการที่สองหลังจากที่เราพบห้องสมุดที่มีอยู่ทั้งหมดเราควรเลือกห้องไหน แต่ละห้องสมุดเหมาะสำหรับความต้องการที่แตกต่างกัน ห้องสมุดเหล่านี้ไม่เทียบเท่ากับประสิทธิภาพและมีความแตกต่างพื้นฐานในการออกแบบ แต่ละห้องสมุดมีลักษณะของตัวเองและใช้คำศัพท์ที่แตกต่างกันเพื่ออธิบาย ดังนั้นการประเมินและเปรียบเทียบไลบรารีไคลเอนต์ FTP จึงเป็นงานที่ยาก
การใช้ส่วนประกอบที่นำกลับมาใช้ใหม่เป็นวิธีการสนับสนุน แต่ในกรณีนี้มันมักจะท้อใจในตอนแรก ต่อมาฉันอาจจะละอายใจเล็กน้อย: หลังจากเลือกห้องสมุด FTP ที่ดีงานที่ตามมานั้นง่ายมากเพียงทำตามกฎง่ายๆ ในปัจจุบันมีห้องสมุดไคลเอนต์ FTP ที่เปิดเผยต่อสาธารณะและฟรีเช่น Simpleftp, J-FTP ฯลฯ และ FTPClients อื่น ๆ อีกมากมาย ดังที่แสดงในตารางต่อไปนี้ตารางไม่สามารถแสดงรายการได้ทั้งหมด หากผู้อ่านมีไลบรารีคลาส FTP ไคลเอนต์ที่ดีกว่าโปรดทำอาหารเสริมเพิ่มเติม
ในบทความนี้ผู้เขียนใช้ J-FTP นี่คือโอเพนซอร์สและไลบรารี FTP ไคลเอนต์ที่ทรงพลังมาก ผู้เขียนชอบมันมากและยังแนะนำให้ผู้อ่านทุกคน ลืมมันฟรีและสร้างโฆษณา
3. ฟังก์ชั่นพื้นฐาน
1. เข้าสู่ระบบ
FTP ใช้สำหรับการถ่ายโอนไฟล์ แต่ในสาระสำคัญ java.net.socket ใช้สำหรับการสื่อสาร รหัสต่อไปนี้เป็นเพียงหนึ่งในวิธีการเข้าสู่ระบบของคลาส net.sf.jftp.net.ftpconnection แน่นอนเพื่อบันทึกเค้าโครงและอธิบายหลักการบางอย่างอย่างชัดเจนในรหัสต่อไปนี้ผู้เขียนได้ลบรหัสที่ไม่จำเป็นบางอย่างเช่นบันทึกและรหัสอื่น ๆ สำหรับรหัสที่สมบูรณ์โปรดดูที่ซอร์สโค้ดของ J-FTP หรือซอร์สโค้ดตัวอย่างของผู้แต่ง ตัวอย่างรหัสต่อไปนี้เหมือนกัน:
เข้าสู่ระบบสาธารณะ (ชื่อผู้ใช้สตริง, รหัสผ่านสตริง) {this.userName = ชื่อผู้ใช้; this.password = รหัสผ่าน; สถานะ int = login_ok; jCon = new jConnection (โฮสต์, พอร์ต); if (jCon.Isthere ()) {in = jCon.getReader (); if (getLine (บวก) == null) // ftp220_service_ready) == null) {ok = false; สถานะ = ออฟไลน์; } if (! getLine (loginack) .startswith (บวก)) // ftp230_logged_in)) {ถ้า (ความสำเร็จ (บวก)) // ftp230_logged_in)) {} else {ok = false; สถานะ = unmle_login_data; }}} else {ถ้า (msg) {log.debug ("ftp ไม่พร้อมใช้งาน!"); ตกลง = เท็จ; สถานะ = generic_failed; }} ถ้า (ตกลง) {Connected = true; ระบบ(); ไบนารี (); สตริง [] advSettings = สตริงใหม่ [6]; if (getOstype (). indexof ("OS/2")> = 0) {list_default = "รายการ"; } if (list.equals ("default")) {// เพิ่งได้รับรายการแรก (อย่างใดมันรู้ก่อนคือคำสั่ง // ftp list) advSettings = loadset.loadset (settings.adv_settings); // *** หากไม่พบไฟล์ให้สร้างและตั้งค่าเป็น list_default ถ้า (advSettings == null) {list = list_default; saveset s = saveset ใหม่ (settings.adv_settings, รายการ); } else {list = advSettings [0]; if (list == null) {list = list_default; }}} if (getostype (). indexof ("mvs")> = 0) {list = "list"; } // *** FireDirectoryUpdate (นี่); FireconnectionInitialized (นี้); } else {fireconnectionfailed (นี่, จำนวนเต็มใหม่ (สถานะ) .toString ()); } สถานะการส่งคืน; - ในวิธีการเข้าสู่ระบบนี้มีคลาส JConnection ซึ่งรับผิดชอบในการสร้างซ็อกเก็ตซ็อกเก็ต ในเวลาเดียวกันคลาสนี้เป็นเธรดแยกต่างหาก ข้อได้เปรียบคือเพื่อให้ความร่วมมือกับการเปลี่ยนแปลงส่วนต่อประสานการเชื่อมต่อซ็อกเก็ตเครือข่ายและงานอื่น ๆ จะถูกประมวลผลเป็นเธรดแยกต่างหากซึ่งเอื้อต่อความเป็นมิตรของอินเทอร์เฟซ ด้านล่างเป็นวิธีการเรียกใช้ของคลาส net.sf.jftp.net.jconnection แน่นอนการเริ่มต้นของเธรดนี้เริ่มต้นขึ้นในตัวสร้างของคลาส JConnection
โมฆะสาธารณะเรียกใช้ () {ลอง {s = ซ็อกเก็ตใหม่ (โฮสต์, พอร์ต); localport = s.getLocalport (); // ถ้า (เวลา> 0) S.SetSotimeout (เวลา); out = new printstream (ใหม่ bufferedOutputStream (s.getOutputStream (), settings.buffersize)); ใน = ใหม่ bufferedReader (ใหม่ inputStreamReader (s.getInputStream ()), settings.buffersize); isok = true; //}} catch (Exception Ex) {Ex.PrintStackTrace (); log.out ("คำเตือน: การเชื่อมต่อปิดเนื่องจากข้อยกเว้น (" + โฮสต์ + ":" + พอร์ต + ")"); isok = false; ลอง {ถ้า ((s! = null) &&! s.isclosed ()) {s.close (); } if (out! = null) {out.close (); } if (in! = null) {in.close (); }} catch (Exception ex2) {ex2.printstacktrace (); log.out ("คำเตือน: มีข้อผิดพลาดมากขึ้นพยายามปิดซ็อกเก็ตและสตรีม"); }} สร้าง = true; -ซ็อกเก็ตในวิธีการเรียกใช้นี้จะอธิบายที่นี่ว่าการใช้งานซ็อกเก็ตไคลเอนต์ประเภทนี้ (เรียกอีกอย่างว่า "ซ็อกเก็ต") ซึ่งเป็นจุดสิ้นสุดการสื่อสารระหว่างสองเครื่อง งานจริงของซ็อกเก็ตดำเนินการโดยอินสแตนซ์ของคลาส socketimpl แอปพลิเคชันใช้โรงงานซ็อกเก็ตที่สร้างซ็อกเก็ตโดยการเปลี่ยนโรงงานซ็อกเก็ตที่สามารถกำหนดค่าตัวเองเพื่อสร้างซ็อกเก็ตที่เหมาะสำหรับไฟร์วอลล์ท้องถิ่น สำหรับคำแนะนำเฉพาะโปรดดูคำแนะนำ API ของ JDK5 โดยเฉพาะอย่างยิ่งในภาษาจีน ฮิฮิ
2 อัปโหลดและดาวน์โหลด
การอัปโหลดไฟล์สามารถแบ่งออกเป็นแบบมัลติเธรดและเธรดเดี่ยวซึ่งค่อนข้างง่ายในสถานการณ์แบบเธรดเดี่ยวในขณะที่อยู่ในสถานการณ์แบบหลายเธรดสิ่งที่ต้องจัดการและระมัดระวังมากขึ้น ด้านล่างคือวิธีการอัปโหลดที่จับโหลดของ net.sf.jftp.net.ftpconnection มีการพิจารณาสองประเภทที่แตกต่างกันเธรดเดี่ยวและมัลติเธรด
public int handleupload (ไฟล์สตริง, realname สตริง) {ถ้า (settings.getEnableMultIthReading () && (! settings.getNouploadMultIthReading ())) {log.out ("วางไข่เธรดใหม่สำหรับการอัปโหลดนี้"); ftptransfer t; if (realname! = null) {t = ใหม่ ftptransfer (โฮสต์, พอร์ต, getLocalPath (), getCachedPwd (), ไฟล์, ชื่อผู้ใช้, รหัสผ่าน, transfer.upload, handler, ผู้ฟัง, realname, crlf); } else {t = ใหม่ ftptransfer (โฮสต์, พอร์ต, getLocalPath (), getCachedPwd (), ไฟล์, ชื่อผู้ใช้, รหัสผ่าน, transfer.upload, Handler, ผู้ฟัง, CRLF); } lastTransfer = t; ส่งคืน new_transfer_spawned; } else {if (settings.getNouploadMultIthReading ()) {log.out ("อัปโหลด multithreading ถูกปิดใช้งาน"); } else {log.out ("multithreading ถูกปิดใช้งานอย่างสมบูรณ์"); } return (realname == null)? อัปโหลด (ไฟล์): อัปโหลด (ไฟล์, RealName); - ในกรณีของมัลติเธรดมีคลาสต่าง ๆ ที่แยกต่างหาก net.sf.jftp.net.ftptransfer แน่นอนในกรณีของมัลติเธรดคลาสนี้จะต้องเป็นเธรดแยกต่างหาก เช่นเดียวกับ JConnection การเริ่มต้นของเธรดก็เริ่มต้นขึ้นในตัวสร้าง ในวิธีการเรียกใช้ไฟล์จะถูกอ่านและส่ง
โมฆะสาธารณะเรียกใช้ () {ถ้า (handler.getConnections (). get (ไฟล์) == null) {handler.addconnection (ไฟล์นี้); } else if (! pause) {log.debug ("โอนไปแล้วในความคืบหน้า:" + ไฟล์); งาน = เท็จ; Stat = 2; กลับ; } บูลีน haspaused = false; ในขณะที่ (หยุดชั่วคราว) {ลอง {runner.sleep (100); if (ผู้ฟัง! = null) {สำหรับ (int i = 0; i <listeners.size (); i ++) {((ConnectionListener) listeners.elementat (i)). updateProgress (ไฟล์, หยุด, -1); }} if (! work) {if (listeners! = null) {สำหรับ (int i = 0; i <listeners.size (); i ++) {((ConnectionListener) listeners.elementat (i)). UpdateProgress (ไฟล์, ลบ, -1); }}}} catch (Exception Ex) {} haspaused = true; } ในขณะที่ ((handler.getConnectionesize ()> = settings.getMaxConnections ()) && (handler.getConnectionsize ()> 0) && work) {ลอง {stat = 4; runner.sleep (400); if (! haspaused && (ผู้ฟัง! = null)) {สำหรับ (int i = 0; i <listeners.size (); i ++) {((ConnectionListener) listeners.elementat (i)). UpdateProgress (ไฟล์, คิว, -1); }} else {break; }} catch (Exception ex) {ex.printstacktrace (); }} if (! work) {if (listeners! = null) {สำหรับ (int i = 0; i <listeners.size (); i ++) {((ConnectionListener) listeners.elementat (i)). UpdateProgress (ไฟล์, ลบ, -1); }} handler.removeConnection (ไฟล์); Stat = 3; กลับ; } เริ่มต้น = true; ลอง {runner.sleep (settings.ftptransferthreadpause); } catch (exception ex) {} con = new ftpConnection (โฮสต์, พอร์ต, remotepath, crlf); Con.setConnectionHandler (Handler); Con.setConnectionListeners (ผู้ฟัง); สถานะ int = con.login (ผู้ใช้, ผ่าน); if (สถานะ == ftpConnection.login_ok) {ไฟล์ f = ไฟล์ใหม่ (localPath); con.setLocalpath (f.getabsolutepath ()); if (type.equals (อัปโหลด)) {if (newName! = null) {transFerStatus = con.upload (ไฟล์, newName); } else {transferstatus = con.upload (ไฟล์); }} else {transferstatus = con.download (ไฟล์ this.newName); }} if (! pause) {handler.removeConnection (ไฟล์); - สำหรับกระบวนการดาวน์โหลดเนื่องจากเป็นกระบวนการผกผันของการอัปโหลดจึงคล้ายกับวิธีการอัปโหลดและวิธีการเขียน ด้วยเหตุผลบางอย่างรหัสไม่ได้อยู่ในรายการ แต่ความคิดและความคิดของมันเหมือนกันทุกประการ โปรดดูซอร์สโค้ดสำหรับผู้อ่าน
4. แถบความคืบหน้า
สามารถจินตนาการได้ว่าหากไม่มีพรอมต์ในระหว่างกระบวนการอัปโหลดหรือดาวน์โหลดผู้ใช้ไม่สามารถตัดสินได้ว่างานจะเสร็จสมบูรณ์หรือไม่ว่างานจะตายและผู้ใช้มักจะทำให้เข้าใจผิดเนื่องจากเวลาอัปโหลดหรือเวลาดาวน์โหลดนานเกินไป ดังนั้นแถบความคืบหน้าจึงมีความสำคัญและใช้งานได้จริง
การใช้งานแถบความคืบหน้านั้นง่ายมาก มันคือการเปิดสองเธรดในโปรแกรม เธรดแรกใช้เพื่อเปลี่ยนค่าของแถบความคืบหน้าแบบไดนามิกในอินเทอร์เฟซในขณะที่เธรดที่สองจะวนวนลูประหว่างกระบวนการอัปโหลดหรือดาวน์โหลด ในลูปนี้มีการอ่านข้อมูลจำนวนหนึ่งเช่น 8192 ไบต์ในแต่ละครั้ง จากนั้นหลังจากผ่านข้อมูลนี้ให้เรียกใช้เมธอด UpdateProgress ในเธรดแรกเพื่ออัปเดตค่าของแถบความคืบหน้าของอินเตอร์เฟส
ในระหว่างกระบวนการอัพโหลดหรือดาวน์โหลด (ดูวิธีการเรียกใช้ของคลาส FTPTransfer ในส่วนก่อนหน้า) คุณสามารถดูวิธี con.upload (ไฟล์, newname), รหัสมีดังนี้
การอัปโหลด int สาธารณะ (ไฟล์สตริง, realname สตริง, inputStream ใน) {hasuploaded = true; log.out ("การอัปโหลด FTP เริ่มต้น:" + สิ่งนี้); สถิติ int; if ((ใน == null) && ไฟล์ใหม่ (ไฟล์) .isdirectory ()) {shortProgress = true; fileCount = 0; baseFile = ไฟล์; datatype = dataconnection.putdir; isDirUpload = true; stat = uploaddir (ไฟล์); shortprogress = false; //system.out.println(FileCount + ":" + basefile); FireProgressUpdate (BaseFile, Dataconnection.dfinished + ":" + fileCount, -1); FireActionFinished (นี้); FireDirectoryUpdate (นี้); } else {dataType = dataConnection.put; stat = rawupload (ไฟล์, realname, in); ลอง {thread.sleep (100); } catch (Exception Ex) {} FireActionFinished (นี่); FireDirectoryUpdate (นี้); } ลอง {thread.sleep (500); } catch (exception ex) {} return stat; -วิธีนี้มีหน้าที่รับผิดชอบในการอัปโหลดจำนวนไบต์ ในความเป็นจริงมันถูกเรียกว่าวิธี Rawupload มันไม่ได้อยู่ในรายการที่นี่ โปรดดูซอร์สโค้ด หลังจากผ่านข้อมูลไบต์นี้เมธอด UpdateProgressBar () ในเธรดหลักจะเรียกโดยการเรียกใช้วิธี FireActionFinished () จริงๆแล้วรหัสมีดังนี้:
void updateprogressBar () {int เปอร์เซ็นต์ = (int) (((ลอย) lfileCompleTesize / (float) lfilesize) * 10000f); pbfile.setValue (เปอร์เซ็นต์); // system.out.println ("===================================================="+เปอร์เซ็นต์); pbfile.setstring (lfilecompletesize / 1024l + " /" + lfilesize / 1024l + "kb"); เปอร์เซ็นต์ = (int) (((ลอย) ltotalcompletesize / (float) ltotalsize) * 10,000f); pbtotal.setstring (ltotalcompletesize / 1024l + " /" + ltotalsize / 1024l + "kb"); pbtotal.setValue (เปอร์เซ็นต์); ทาสีใหม่ (); - มีการใช้แถบความคืบหน้าสองแถบด้านบน แถบความคืบหน้าแรกแสดงถึงความคืบหน้าการอัปโหลดหรือดาวน์โหลดของไฟล์ปัจจุบันและแถบความคืบหน้าที่สองแสดงถึงความคืบหน้าของการดาวน์โหลดหรืออัปโหลดไฟล์ทั้งหมด ในเวลาเดียวกันเพื่อสร้างความก้าวหน้าหรือการเปลี่ยนแปลงที่ชัดเจนยิ่งขึ้นค่าสูงสุดของแถบความคืบหน้าจะถูกตั้งค่าเป็น 10,000 ผ่าน PBFile.SetMaximum (10,000) และ PBTOTAL.SETMAXIMUM (10,000) แทนที่จะเป็น 100 ที่เราตั้งไว้ ผู้เขียนเชื่อว่าสิ่งนี้ดีกว่าเพราะบางครั้งเมื่ออัปโหลดหรือดาวน์โหลดการเปลี่ยนแปลงอาจมีขนาดค่อนข้างเล็กเนื่องจากเหตุผลของเครือข่าย หากตั้งค่าเป็น 100 การเปลี่ยนแปลงจะไม่ชัดเจนโดยเฉพาะ
ด้านบนเป็นบทความพื้นฐานสำหรับการอัปโหลดและดาวน์โหลดไฟล์ FTP ขนาดใหญ่ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น