تقدم هذه المقالة كيفية استخدام المكتبات المتوفرة الموجودة في Java لكتابة رمز عميل FTP وتطويرها في عناصر تحكم في Applet لجعل الدُفعات ، وتحميل الملفات الكبيرة وتنزيل عناصر التحكم بناءً على الويب. استنادًا إلى سلسلة من مكتبات عملاء FTP ، توفر المقالة تفسيرات مفصلة وتطبيقات رمز على واحدة من مكتبة J-FTP الأكثر شيوعًا وقوة ، مثل أشرطة التقدم ، واستمرار نقطة التوقف ، ورسم خرائط الشبكات الداخلية والخارجية ، ووظائف JavaScript في Applet. من المأمول أن يلعب هذا المقال دورًا في جذب اليشم.
1. مقدمة
أثناء تنفيذ المشروع ، ظهرت متطلبات تحميل الملف وتنزيلها على شبكة الإنترنت. يحتاج المستخدمون في جميع أنحاء المقاطعة (أو على مستوى البلاد) إلى تحميل بعض الملفات إلى خادم الملفات في مركز معين. يتم استخدام هذه المستندات لبعض الإنشاءات الهندسية على نطاق واسع ، والتي قد تشمل مشاريع البناء بقيمة عشرات الملايين أو حتى مئات الملايين من يوان. تحتوي الملفات على ثلاث خصائص مميزة: الأول هو أن الملف كبير ، والذي قد يصل إلى 50 مترًا ؛ والثاني هو أن عدد الملفات كبير ، والذي قد يكون حوالي 15 ؛ والثالث هو أن التوقيعات الرقمية وتشفير البيانات مطلوبة من حيث أمان البيانات.
بادئ ذي بدء ، فكر في طريقة الإرسال المستندة إلى HTTP. ومع ذلك ، من خلال المقارنة ، وجدت بسرعة أن الاحتياجات أعلاه قد تلت:
1: يبدو أن التحميل باستخدام بروتوكول HTTP أكثر ملاءمة لراحة برمجة الويب ؛ يعد تحميل الملفات أقل من 1 متر أسرع قليلاً من تحميل الملفات باستخدام بروتوكول FTP. ولكن قد لا يكون هناك ما تفعله حيال نقل الدُفعات والملفات الكبيرة. بالطبع ، لها أيضًا مزاياها ، على عكس FTP ، من الضروري بدء خدمة FTP على جانب الخادم.
2: تحميل الملفات بملفات أكبر من 1M باستخدام بروتوكول FTP أسرع من HTTP. كلما زاد عدد الملفات ، ستكون سرعة التحميل أسرع عدة مرات من سرعة تحميل HTTP. وكتابة البرامج في جافا ؛ FTP أكثر ملاءمة من HTTP.
استخدم المؤلف مرة واحدة VB وكتب عناصر تحكم ActiveX لتحميل وتنزيل ملفات الدُفعات ، كما أن وظائفه قوية جدًا. إنه نظرًا لعدم وجود توقيع رقمي خاص لملفات CAB أو OCX ، من الضروري إجراء إعدادات مملة للعميل ، مثل إعداد موقع آمن ، وتقليل مستوى أمان العميل ، وما إلى ذلك ، تم التخلي عن بعض الحلول.
في الوقت نفسه ، بالنظر إلى أن الملفات يجب توقيعها رقميًا وتشفيرها على العميل ، فقد تقرر استخدام Applet لتنفيذها. . قبل تحميل الملف ، يمكن الحصول على معلومات مفتاح USBKEY المحلية من العميل لإكمال التشفير والمعالجة المميزة للملف الذي تم تحميله. على الرغم من أن استخدام Applet يتطلب تثبيت بيئة وقت تشغيل JRE على العميل ، مما يجلب بعض الإزعاج لإدارة العميل واستخدامه ، فقد يكون سعرًا صغيرًا نسبيًا لمقارنة أمان هذا العدد الكبير من الملفات والملفات.
لتلخيص بيئة التشغيل:
FTP Server Side: Serv-U ، برنامج جانب Server Server Professional ، هناك تنزيلات جاهزة للبرامج على الإنترنت ، بالطبع قد يكتب القراء أيضًا برنامج تلقي ملف FTP من جانب الخادم لشرحه. إذا لم تكن هناك متطلبات أو وظائف خاصة ، فيجب أن تكون Serv-U قادرة على تلبية احتياجات التحميل والتنزيل العام ؛
العميل: Java Applet ، وهي تقنية جعلت Java شهيرة مرة أخرى ثم زعمت أنها قابلة للمقارنة مع Microsoft's ActiveX. بالطبع ، الآن 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 للاتصال. الرمز التالي هو مجرد واحدة من طرق تسجيل الدخول الخاصة بـ Class Net.sf.jftp.net.ftpconnection. بالطبع ، من أجل حفظ التصميم وشرح بعض المبادئ بوضوح في الكود التالي ، قام المؤلف بإزالة بعض الرموز غير الضرورية ، مثل السجلات والرموز الأخرى. للحصول على الرمز الكامل ، يرجى الرجوع إلى الكود المصدري لـ J-FTP أو رمز المصدر للمؤلف. أمثلة الكود التالية هي نفسها:
تسجيل الدخول العام int (اسم المستخدم ، كلمة مرور السلسلة) {this.userName = username ؛ this.password = كلمة المرور ؛ int status = login_ok ؛ JCON = JConnection New JConnection (مضيف ، منفذ) ؛ if (jcon.isthere ()) {in = jCon.GetReader () ؛ if (getLine (evential) == null) // ftp220_service_ready) == null) {ok = false ؛ الحالة = غير متصل ؛ } if (! getLine (loginack) .startswith (موجب)) // ftp230_logged_in)) {if (success (evential)) // ftp230_logged_in)) {} else {ok = false ؛ الحالة = خطأ _login_data ؛ }}} آخر {if (msg) {log.debug ("ftp غير متوفر!") ؛ موافق = خطأ ؛ الحالة = generic_failed ؛ }} if (ok) {connected = true ؛ نظام()؛ ثنائي()؛ سلسلة [] advSettings = سلسلة جديدة [6] ؛ if (getostype (). indexof ("OS/2")> = 0) {list_default = "list" ؛ } if (list.equals ("default")) {// فقط احصل على العنصر الأول (بطريقة ما يعرف أولاً هو // ftp list command) advSettings = loadset.loadset (settings.adv_settings) ؛ // *** إذا لم يتم العثور على الملف ، فقم بإنشائه وقم بتعيينه على list_default if (advSettings == null) {list = list_default ؛ SaveSet S = SaveSet جديد (الإعدادات. } آخر {list = advSettings [0] ؛ if (list == null) {list = list_default ؛ }}} if (getostype (). indexof ("mvs")> = 0) {list = "list" ؛ } // *** fireDirectoryUpdate (هذا) ؛ النهر الناري (هذا) ؛ } آخر {fireConnectionFailed (هذا ، عدد صحيح جديد (الحالة) .ToString ()) ؛ } حالة الإرجاع ؛ } في طريقة تسجيل الدخول هذه ، هناك فئة JConnection ، وهي مسؤولة عن إنشاء مآخذ التوصيل. في الوقت نفسه ، هذه الفئة هي موضوع منفصل. الميزة هي أنه من أجل التعاون مع تغييرات الواجهة ، تتم معالجة اتصالات مأخذ التوصيل الشبكة والمهام الأخرى كخيط منفصل ، وهو ما يفضي إلى الود الواجهة. فيما يلي طريقة التشغيل لفئة Net.sf.jftp.net.jconnection. بالطبع ، يتم بدء تشغيل هذا الموضوع في مُنشئ فئة JConnection.
public void run () {try {s = new Socket (host ، port) ؛ localport = s.getlocalport () ؛ // if (time> 0) S.SetSotimeout (time) ؛ out = new printstream (جديد bufferedoutputstream (s.getOutputStream () ، settings.buffersize)) ؛ في = جديد BufferedReader (New InputStreamReader (S.GetInputStream ()) ، Settings.buffersize) ؛ ISOK = صحيح ؛ //}} catch (استثناء ex) {ex.printStackTrace () ؛ log.out ("تحذير: اتصال مغلق بسبب الاستثناء (" + مضيف + ":" + port + ")") ؛ ISOK = خطأ ؛ حاول {if ((s! = null) &&! s.isclosed ()) {s.close () ؛ } if (out! = null) {out.close () ؛ } if (in! = null) {in.close () ؛ }} catch (استثناء ex2) {ex2.printStackTrace () ؛ log.out ("تحذير: حصلت على المزيد من الأخطاء التي تحاول إغلاق المقبس والتدفقات") ؛ }} تم إنشاؤه = صحيح ؛ }سيشرح هنا المقبس في طريقة التشغيل هذه أن هذا النوع من تنفيذ مآخذ العميل (يُطلق عليه أيضًا "مآخذ") ، والتي هي نقاط نهاية الاتصال بين ماكينات. يتم تنفيذ العمل الفعلي للمقبس بواسطة مثيل من فئة SocketImpl. يقوم أحد التطبيقات بتنفيذ مصنع المقبس الذي ينشئ مآخذ عن طريق تغيير مصنع المقبس الذي يمكنه تكوين نفسه لإنشاء مآخذ مناسبة لجدار الحماية المحلي. للحصول على تعليمات محددة ، يرجى الرجوع إلى تعليمات API الخاصة بـ JDK5 ، ويفضل أن تكون باللغة الصينية. هيه.
2 تحميل وتنزيل
يمكن تقسيم ملفات تحميل إلى سلسلة متعددة الخيوط وروح واحدة ، وهو أمر بسيط نسبيًا في المواقف المفردة ، بينما في المواقف متعددة الخيوط ، يتم التعامل مع المزيد من الأشياء وأكثر حذراً. فيما يلي طريقة التحميل للمقبض لـ net.sf.jftp.net.ftpconnection. تم النظر في نوعين مختلفين ، خيط واحد ومتعدد الخيوط.
public int gallepload (ملف السلسلة ، سلسلة realName) {if (settings.getEnablEmultIthReading () && (! settings.getnouploadmultithReading ())) {log.out ("مؤشر ترابط جديد لهذا التحميل.") ؛ ftptransfer t ؛ if (realName! = null) {t = new ftptransfer (المضيف ، المنفذ ، getLocalPath () ، getCachedPwd () ، ملف ، اسم المستخدم ، كلمة المرور ، transfer.upload ، معالج ، المستمعين ، RealName ، crlf) ؛ } آخر {t = new ftptransfer (المضيف ، المنفذ ، getLocalPath () ، getCachedPwd () ، ملف ، اسم المستخدم ، كلمة المرور ، transfer.upload ، معالج ، المستمعين ، crlf) ؛ } lastTransfer = t ؛ إرجاع new_transfer_spawned ؛ } else {if (settings.getNouploAdmultIthReading ()) {log.out ("تحميل multiThReading.") ؛ } آخر {log.out ("MultiThreading معطل تمامًا.") ؛ } العودة (RealName == NULL)؟ تحميل (ملف): تحميل (ملف ، اسم RealName) ؛ }} في حالة Multi-Thorreading ، هناك فئة منفصلة net.sf.jftp.net.ftptransfer. بالطبع ، في حالة متعدد الخيوط ، يجب أن يكون هذا الفئة موضوعًا منفصلًا. على غرار JConnection ، يتم بدء بدء تشغيل خيطه أيضًا في المنشئ. في طريقة التشغيل ، يتم قراءة الملف ونقله.
public void run () {if (handler.getConnections (). get (file) == null) {handler.addconnection (file ، this) ؛ } آخر إذا (! توقف) {log.debug ("نقل بالفعل:" + ملف) ؛ العمل = خطأ ؛ STAT = 2 ؛ يعود؛ } boolean haspaused = false ؛ بينما (توقف مؤقت) {try {runner.sleep (100) ؛ if (المستمعين! = null) {for (int i = 0 ؛ i <leaders.size () ؛ i ++) {(connectionListener) leaders.elementat (i)). }} if (! work) {if (المستمعين! = null) {for (int i = 0 ؛ i <leaders.size () ؛ i ++) {(connectionListener) leaders.elementat (i)). }}}} catch (استثناء ex) {} haspaused = true ؛ } بينما ((handler.getConnectionSize ()> = settings.getMaxConnections ()) && (handler.getConnectionSize ()> 0) && work) {try {stat = 4 ؛ Runner.Sleep (400) ؛ if (! haspaused && (المستمعين! = null)) {for (int i = 0 ؛ i <leaders.size () ؛ i ++) {(connectionListener) leaders.elementat (i)). }} آخر {break ؛ }} catch (استثناء ex) {ex.printStackTrace () ؛ }} if (! work) {if (المستمعين! = null) {for (int i = 0 ؛ i <leaders.size () ؛ i ++) {(connectionListener) leaders.elementat (i)). }} handler.removeconnection (ملف) ؛ STAT = 3 ؛ يعود؛ } بدأ = صحيح ؛ Try {Runner.sleep (Settings.ftpTransferThreadPause) ؛ } catch (استثناء ex) {} con = new ftpconnection (المضيف ، المنفذ ، remotepath ، crlf) ؛ consetConnectionHandler (معالج) ؛ Con.SetConnectionListeners (المستمعين) ؛ int status = con.login (المستخدم ، تمرير) ؛ if (status == ftpConnection.login_ok) {file f = new file (localPath) ؛ consetlocalpath (f.getabsolutepath ()) ؛ if (type.equals (تحميل)) {if (newName! = null) {transferstatus = con.upload (file ، newName) ؛ } آخر {transferstatus = con.upload (file) ؛ }} آخر {transferstatus = con.Download (ملف ، this.newName) ؛ }} if (! pause) {handler.removeconnection (file) ؛ }} بالنسبة لعملية التنزيل ، لأنها عملية عكسية للتحميل ، فهي تشبه طريقة التحميل وطريقة الكتابة. لبعض الأسباب ، لا يتم سرد الكود ، ولكن أفكاره وأفكاره متشابهة تمامًا. يرجى الرجوع إلى الكود المصدر للقراء.
4. شريط التقدم
يمكن تخيل أنه إذا لم يكن هناك موجه أثناء عملية التحميل أو التنزيل ، فلا يمكن للمستخدم الحكم على ما إذا كانت المهمة قد اكتملت أو ما إذا كانت المهمة قد ماتت ، وغالبًا ما يكون المستخدم مضللاً بسبب وقت التحميل أو وقت التنزيل لفترة طويلة. لذلك ، شريط التقدم مهم للغاية وعملي.
تنفيذ شريط التقدم بسيط للغاية. إنه لفتح خيطين في البرنامج. يتم استخدام الخيط الأول لتغيير قيمة شريط التقدم ديناميكيًا على الواجهة ، بينما يشكل مؤشر الترابط الثاني حلقة أثناء عملية التحميل أو التنزيل. في هذه الحلقة ، تتم قراءة عدد معين من البيانات مثل 8192 بايت في كل مرة. ثم بعد اجتياز هذه البيانات ، اتصل بطريقة UpdateProgress في مؤشر الترابط الأول لتحديث قيمة شريط التقدم في الواجهة.
أثناء عملية التحميل أو التنزيل (راجع طريقة تشغيل فئة FTPTransfer في القسم السابق) ، يمكنك عرض طريقة Con.Upload (ملف ، newName) ، الرمز كما يلي.
int public expload (ملف السلسلة ، string realName ، inputStream in) {hasuploaded = true ؛ log.out ("FTP upload بدأ:" + هذا) ؛ int stat ؛ if ((in == null) && new file (file) .isdirectory ()) {sterprogress = true ؛ fileCount = 0 ؛ basefile = ملف ؛ نوع البيانات = dataconnection.putdir ؛ isdirupload = صحيح ؛ STAT = UploadDir (ملف) ؛ اختصار = خطأ ؛ //system.out.println(filecount + ":" + basefile) ؛ fireprogressUpdate (basefile ، dataconnection.dfinish + ":" + fileCount ، -1) ؛ FireActionfinishized (هذا) ؛ firedirectoryupdate (هذا) ؛ } آخر {datatype = dataConnection.put ؛ STAT = RAWUPLOAD (ملف ، realName ، in) ؛ حاول {thread.sleep (100) ؛ } catch (استثناء ex) {} fireActionFinishiSh (this) ؛ firedirectoryupdate (هذا) ؛ } جرب {thread.sleep (500) ؛ } catch (استثناء ex) {} return stat ؛ }هذه الطريقة هي المسؤولة عن تحميل عدد معين من البايتات. في الواقع ، يطلق عليه طريقة Rawupload. لم يتم سردها هنا. يرجى الرجوع إلى رمز المصدر. بعد تمرير بيانات البايت هذه ، يتم استدعاء طريقة UpdateProgressBar () في الخيط الرئيسي عن طريق استدعاء طريقة FireActionfinished (). في الواقع الرمز كما يلي:
محمي void updateProgressBar () {int ٪ = (int) (((float) lfileCompletesize / (float) lfilesize) * 10000f) ؛ pbfile.setValue (في المئة) ؛ // system.out.println ("================================================="+٪) ؛ pbfile.SetString (lfileCompletesize / 1024l + " /" + lfilesize / 1024l + "kb") ؛ النسبة المئوية = (int) (((float) ltotalcompletesize / (float) ltotalsize) * 10000f) ؛ pbtotal.SetString (ltotalcompletesize / 1024l + " /" + ltotalsize / 1024l + "kb") ؛ pbtotal.setValue (في المئة) ؛ REPAINT () ؛ } يتم استخدام قضبان التقدم أعلاه. يمثل شريط التقدم الأول التحميل أو تنزيل التقدم في الملف الحالي ، ويمثل شريط التقدم الثاني تقدم جميع الملفات تنزيل أو تحميل. في الوقت نفسه ، من أجل توليد تقدم أو تغيير أكثر وضوحًا ، يتم تعيين القيمة القصوى لشريط التقدم على 10000 من خلال pbfile.setMaximum (10000) و pbtotal.setmaximum (10000) ، بدلاً من 100 نضعها عادة. يعتقد المؤلف أن هذا أفضل ، لأنه في بعض الأحيان عند التحميل أو التنزيل ، قد تكون التغييرات صغيرة نسبيًا لأسباب الشبكة. إذا تم ضبطه على 100 ، فإن التغيير غير واضح بشكل خاص.
ما سبق هو المقالة الأساسية لتحميل وتنزيل مجموعات كبيرة من ملفات FTP. آمل أن يكون ذلك مفيدًا لتعلم الجميع ، وآمل أن يدعم الجميع wulin.com أكثر.