闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁惧墽鎳撻—鍐偓锝庝簼閹癸綁鏌i鐐搭棞闁靛棙甯掗~婵嬫晲閸涱剙顥氬┑掳鍊楁慨鐑藉磻閻愮儤鍋嬮柣妯荤湽閳ь兛绶氬鎾閻樻爠鍥ㄧ厱閻忕偛澧介悡顖氼熆鐟欏嫭绀€闁宠鍨块、娆戠磼閹惧墎绐楅梻浣告啞椤棝宕橀敐鍡欌偓娲倵楠炲灝鍔氭繛鑼█瀹曟垿骞橀懜闈涙瀭闂佸憡娲﹂崜娑⑺囬鐔虹瘈闁冲皝鍋撻柛鏇炵仛閻や礁螖閻橀潧浠滄俊顐g箓椤曪綁顢氶埀顒€鐣烽悡搴唵妞ゅ繋鐒﹀▍濠囨煙椤旂瓔娈滈柡浣瑰姈閹柨鈹戦崼婵嗘瘓闂佽娴烽幊鎾诲箟閿涘嫭宕查柛鏇ㄥ幗椤洟鏌熼悜妯诲鞍缂傚秴娲弻鏇熺箾閸喖濮㈤梺鑽ゅ枂閸斿矂鈥旈崘顔嘉ч幖绮光偓鑼嚬缂傚倷绶¢崰妤呭箰閹间焦鍋╅柣鎴f绾偓闂佺粯鍔曠粔鍫曞窗閺嶎厼绠栨繛鍡樻尭缁狅絾绻濋棃娑欐悙妞わ腹鏅犲娲箮閼恒儲鏆犻梺鎼炲妼濠€鍗炍i幇鏉跨閻庢稒锚椤庢挻绻濆▓鍨灍闁糕晛鐗婄粋宥呪攽鐎n亞鐤勯梺闈浥堥弲娑㈡倷婵犲洦鐓忓┑鐐茬仢閳ь剚顨堢划璇差潩椤掑瀵岄梺闈涚墕濡稒鏅堕鍕厽闁哄啯鍨垫晶鎾煟閹垮啫澧存い銏☆殜瀹曟帒螖閳ь剚绂嶆ィ鍐╁仭婵炲棗绻愰顏嗙棯閻愵剚鍊愰柡灞剧⊕閹棃鏁愰崱妯荤槗闁诲孩顔栭崳顕€宕戞繝鍥╁祦婵☆垵鍋愮壕鍏间繆椤栨粎甯涙い蹇曞枛濮婄粯鎷呴懞銉с€婇梺闈╃秶缁犳捇鐛箛娑欐櫢闁跨噦鎷�濠电姷鏁告慨鐑藉极閸涘﹥鍙忛柣鎴f閺嬩線鏌涘☉姗堟敾闁告瑥绻橀弻锝夊箣閿濆棭妫勯梺鍝勵儎缁舵岸寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ゆい顓犲厴瀵鏁愭径濠勭杸濡炪倖甯婇悞锕傚磿閹惧墎纾藉ù锝呮惈灏忛梺鍛婎殕婵炲﹤顕f繝姘亜闁稿繐鐨烽幏濠氭煟鎼淬劍娑у鐟帮工鍗辨い鏂垮⒔绾捐棄霉閿濆懏鎯堥崯鎼佹⒑閸濄儱校闁绘濮撮锝嗙節濮橆儵鈺呮煃閸濆嫬鈧憡绂嶅⿰鍫熲拺闁告稑锕︾粻鎾绘倵濮橆剚鍤囧┑顔瑰亾闂侀潧鐗嗗Λ娑㈠储闁秵鈷戦梻鍫熻儐瑜版帒纾块梺顒€绉撮悞鍨亜閹哄棗浜惧┑鐘亾闂侇剙绉寸粻鏌ユ煏韫囨洖袥婵℃彃鐗撻弻鏇$疀閺囩倫銏ゆ煠閺夎法浠㈤柍瑙勫灴閸┿儵宕卞Δ鍐ф樊婵$偑鍊栧▔锕傚炊椤垶顥夐柣搴$畭閸庨亶藝娴兼潙鐓曢柟瀵稿Х绾惧ジ鎮楅敐搴′航闁稿簺鍎甸弻娑欐償閵忕姴顫庣紓浣介哺鐢偤骞忛悩璇茬闁圭儤鎸婚鎺戔攽閻樻鏆滅紒杈ㄦ礋瀵偆鎷犻懠顒佹闂佺粯姊婚埛鍫ュ极瀹ュ棙鍙忔俊顖氥仒閸氼偊鏌℃径瀣€愭慨濠勭帛閹峰懘宕妷锔锯偓顔尖攽閳╁啨浠犻柛鏂块叄楠炲繒鈧綆鍠栭拑鐔兼煏婢跺牆鍔ら柨娑欑洴濮婅櫣鎲撮崟顐ゎ槰濡炪倖娉﹂崶褏顦ㄩ梺閫炲苯澧撮柟顔煎槻楗即宕橀悙顑芥瀰闁诲孩顔栭崰妤呭箖閸屾凹鍤曟い鏇楀亾鐎规洖銈搁幃銏ゅ传閸曨偅杈堥梻鍌氬€烽懗鍓佸垝椤栨娲冀椤撶偟锛欓梺闈╁瘜閸樻悂宕戦幘鎰佹僵闁绘劦鍓欓锟�
开发学院软件开发Java 开放源码 CMS 入门,第 5 部分: 为 Jakarta Slide... 阅读

开放源码 CMS 入门,第 5 部分: 为 Jakarta Slide 构建 PHP WebDAV 客户机

 2010-04-16 00:00:00 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁惧墽鎳撻—鍐偓锝庝簻椤掋垺銇勯幇顖毿撻柟渚垮妼椤粓宕卞Δ鈧獮濠勭磽閸屾艾鈧懓顫濋妸鈺佺疅缂佸顑欓崥瀣煕椤愵偅绶氱紓鍐╂礋濮婂宕掑▎鎴М濠电姭鍋撻梺顒€绉甸幆鐐哄箹濞n剙濡肩紒鎰殜閺屸€愁吋鎼粹€茬敖婵炴垶鎸哥粔鐢稿Φ閸曨垰鍐€妞ゆ劦婢€濞岊亪姊虹紒妯诲蔼闁稿海鏁诲濠氭晲婢跺﹤宓嗛梺缁樺姈缁佹挳宕戦幘璇叉嵍妞ゆ挻绋戞禍鐐叏濡厧浜鹃悗姘炬嫹闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁惧墽鎳撻—鍐偓锝庝簼閹癸綁鏌i鐐搭棞闁靛棙甯掗~婵嬫晲閸涱剙顥氬┑掳鍊楁慨鐑藉磻濞戔懞鍥偨缁嬫寧鐎梺鐟板⒔缁垶宕戦幇鐗堢厵缂備焦锚缁椦囨煃瑜滈崜锕傚矗閸愵煈娼栭柛婵嗗珔瑜斿畷鎯邦槾濞寸姴銈稿铏规嫚閼碱剛顔夐梺鐓庣秺缁犳牠骞冩ィ鍐╁€婚柦妯侯槼閹芥洟姊洪棃娑辨濠碘€虫喘瀹曘垽鎮介崨濞炬嫼闁荤喐鐟ョ€氱兘宕箛娑欑厱闁绘ê纾晶鐢告煏閸℃鈧湱缂撴禒瀣窛濠电姴瀚獮鍫ユ⒑绾懎顥嶉柟娲讳簽濡叉劙寮撮悢鍝勨叞闂傚倸鍊风欢姘缚瑜嶇叅闁靛牆娲犻崑鎾愁潩椤愩垹绁梺缁樹緱閸o綁鐛幒鎳虫棃鍩€椤掑倻涓嶉柨婵嗘缁♀偓闂傚倸鐗婄粙鎴﹀汲濞嗗緷鐟扳堪閸垻鏆梺鍝勭焿缂嶄焦鎱ㄩ埀顒勬煃閹増纭炬繝鈧潏銊х彾闁哄洨鍠撶弧鈧┑顔斤供閸橀箖宕㈤悽鍛娾拺缂備焦锚婵箓鏌涢幘鏉戝摵闁诡喗蓱濞煎繘濡搁妶鍥╃暰闂備礁婀辩划顖滄暜閻愬瓨娅犳繛鎴炴皑绾捐偐绱撴担璐細婵炴彃顕埀顒冾潐濞叉牕鐣烽鍐簷闂備礁鎲¢崝鏇㈠疮閻樿绀堟繝闈涚墛瀹曞弶绻涢幋鐐ㄧ細闁哄棗妫楅埞鎴︽偐鏉堫偄鍘¢梺杞扮劍閻楁粎妲愰幘瀛樺濞寸姴顑呴幗鐢告⒑閸︻厽鍤€婵炲眰鍊濋幃楣冩倻閽樺顔婇梺瑙勬儗閸樹粙宕撻悽鍛娾拺闁荤喐婢橀幃渚€鏌i幒鐐电暤闁诡喗顨婇獮鏍ㄦ媴閸忓瀚藉┑鐐舵彧缁插潡宕曢妶澶婂惞闁逞屽墴濮婃椽骞栭悙娴嬪亾閺嶎厽鍋嬮柣妯垮吹瀹撲線鐓崶銊р姇闁哄懏鎮傞弻銊╂偆閸屾稑顏�婵犵數濮烽弫鍛婃叏閻戣棄鏋侀柛娑橈攻閸欏繘鏌i幋锝嗩棄闁哄绶氶弻娑樷槈濮楀牊鏁鹃梺鍛婄懃缁绘垿濡甸崟顖氱闁告鍋熸禒鑲╃磽娴e搫顎岄柛銊ョ埣瀵鈽夐姀鐘电杸闂傚倸鐗婄粙鎺楁倶閸儲鍊甸柣鐔哄閸熺偟绱掔拠鎻掓殻濠碉紕鏁诲畷鐔碱敍濮橀硸鍟嬮梺璇查叄濞佳囧箺濠婂牊鍋╁┑鍌氭啞閳锋垹鐥鐐村婵炲吋鍔栫换娑㈡嚑椤掆偓閺嬪孩銇勯銏㈢缂佽鲸甯掕灒闁兼祴鏅滈崵宀勬⒒娓氣偓閳ь剛鍋涢懟顖涙櫠椤旇偐鏆嗛柨婵嗙墕閸斿灚銇勯敂鐣屽弨闁诡噯绻濇俊鑸靛緞鐎n剙甯鹃梻浣稿閸嬪懐鎹㈤崘顔肩;妞ゅ繐鎳愮粻鍓р偓鐟板閸犳洜鑺辨繝姘畾闁绘柨鍚嬮埛鎴︽倵閸︻厼校闁靛棗鍟撮弻銈夊礃閼碱剙鐓熼悗瑙勬礃缁诲牓寮崘顔肩劦妞ゆ帒瀚ч埀顒佹瀹曟﹢顢欓崲澹洦鐓曢柍鈺佸枤濞堟﹢鏌i悢绋垮婵﹥妞介幃鈩冩償閳╁啯鐦i梻浣虹帛閻楁洟濡剁粙璺ㄦ殾闁绘垶岣跨弧鈧梺鎼炲劀閸愩劎銈梻鍌欑窔濞佳勵殽韫囨洘顫曢柡鍥ュ灩閸屻劍銇勮箛鎾跺闁抽攱鍨块弻鐔兼嚃閳轰椒绮堕梺鍛婃⒐椤ㄥ﹪寮婚敓鐘插窛妞ゆ棃鏁慨鍥╃磽娴gǹ鈧湱鏁悢濡撳洨鈧潧鎽滅壕濂稿级閸稑濡肩紒妤佺缁绘盯鎮℃惔锝囶啋闂佺硶鏂侀崜婵嬪箯閸涘瓨鐓ラ悗锝呯仛缂嶆姊婚崒姘偓宄懊归崶褜娴栭柕濞炬櫆閸婂潡鏌ㄩ弴鐐测偓鍝ョ不閺屻儲鐓曢柕澶樺枛婢ь噣鏌$€b晝绐旈柡宀€鍠栧畷婊嗩槾閻㈩垱鐩弻锟犲川椤旇棄鈧劙鏌$仦璇插闁诡喓鍊濆畷鎺戔槈濮楀棔绱�闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁惧墽鎳撻—鍐偓锝庝簻椤掋垺銇勯幇顖毿撻柟渚垮妼椤粓宕卞Δ鈧獮濠勭磽閸屾艾鈧懓顫濋妸鈺佺疅缂佸顑欓崥瀣煕椤愵偅绶氱紓鍐╂礋濮婂宕掑▎鎴М濠电姭鍋撻梺顒€绉甸幆鐐哄箹濞n剙濡肩紒鎰殜閺屸€愁吋鎼粹€茬敖婵炴垶鎸哥粔鐢稿Φ閸曨垰鍐€妞ゆ劦婢€濞岊亪姊虹紒妯诲蔼闁稿海鏁诲濠氭晲婢跺﹤宓嗛梺缁樺姈缁佹挳宕戦幘璇叉嵍妞ゆ挻绋戞禍鐐叏濡厧浜鹃悗姘炬嫹  闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻锝夊箣閿濆憛鎾绘煕閵堝懎顏柡灞诲€濆畷顐﹀Ψ閿旇姤鐦庡┑鐐差嚟婵潧顫濋妸褎顫曢柟鎹愵嚙绾惧吋绻涢崱妯虹瑨闁告﹫绱曠槐鎾寸瑹閸パ勭彯闂佹悶鍔岄悥鍏间繆閹绢喖绀冩い鏃傚帶缁愭盯姊洪崫鍕垫Ч闁搞劌缍婂畷銏犆洪鍛偓鍨殽閻愯尙浠㈤柛鏃€纰嶉妵鍕晜鐠囪尙浠搁悗瑙勬穿缁绘繈鐛惔銊﹀殟闁靛/鍐ㄥ闂傚倸饪撮崑鍕洪敃鈧叅闁哄秲鍔庢晶锟犳⒒閸屾瑦绁版い鏇嗗應鍋撻崹顐㈡诞鐎规洘绮撻幃銏$附婢跺绋侀梻浣瑰劤缁绘劕锕㈡潏鈺侇棜闁稿繘妫跨换鍡樸亜閺嶃劎顣查柟顖氱墛閵囧嫰顢曢姀銏㈠姱濠殿喖锕ュ钘夌暦閻戠瓔鏁囨繛鎴炵懃閻濋亶姊绘担鍛靛綊顢栭崨顓囨稑鈹戠€n亞鐣鹃梺閫炲苯澧柕鍥у缁犳盯骞樼€垫悶鍋愭繝纰樻閸ㄦ壆鈧碍婢橀~蹇撁洪鍕炊闂佸憡娲﹂崜姘跺箯閸楃偐鏀介柣鎰絻缁狙冪暆閿濆懏鍋ユ鐐村灴婵偓闁绘﹩鍋呴弬鈧┑鐘垫暩婵鈧凹鍣e鍫曞箹娴e厜鎷洪梺鍛婄箓鐎氼厼顔忓┑鍡忔斀妞ゆ梹鍎抽崢鎾煙椤旇宓嗗┑锛勫厴閸╋繝宕掑Δ浣割伜婵犵數鍋犻幓顏嗗緤娴犲绠规い鎰╁€栭弳婊堟偣鏉炴媽顒熼柣鏂挎閺岋綁鎮㈠畡鎵泿闂佽 鍋撻柤濮愬€楃壕濂告煕鐏炵偓鐨戠€涙繂螖濡ゅ﹣绨烽柛妤€鍟块悾鐑芥偂鎼搭喗鍍甸梺鎸庣箓閹冲秵绔熼弴銏♀拺闁告繂瀚弳娆撴煟濡も偓濡稓鍒掗崼銉ョ闁崇懓銇樼花濠氭椤愩垺鎼愭繛瀵稿厴钘濋柨鏇楀亾闂囧绻濇繝鍌滃ⅱ闁伙絾妞介弻锛勪沪鐠囨彃顬堥梺瀹狀潐閸ㄥ灝鐣烽崡鐐╂闁瑰吀绀佹禍鐐繆閵堝倸浜惧銈庡弨閸庡篓娓氣偓閺屾盯鎮╁畷鍥р拰濠电姭鍋撳〒姘e亾婵﹨娅g槐鎺懳熼弴鐔风伌闁诡喚鍏樻俊鐤槷闁稿鎸搁~婵嬫偂鎼淬垻浜剧紓鍌欑贰閸犳氨鍒掗鐐参ч柨婵嗩槸缁€鍐煃閸濆嫬鏆欐鐐茬墛娣囧﹪鎮欓鍕ㄥ亾閺嶎厼绀夐柟杈剧畱绾惧綊鏌¢崶銉ョ仼闁告垹濞€楠炴牕菐椤掆偓婵′粙鏌i幘璺烘灈闁绘搩鍋婂畷鎯邦檨闁稿骸绻橀弻娑㈠籍閳ь剛鍒掗幘璇茶摕闁哄洢鍨归悙濠勬喐瀹ュ鏁傛い鎾跺Л閸嬫挸鈻撻崹顔界亶濠电偛鍚嬮悷銊╂倶閹烘鈷戦柛娑橈功缁犳捇鎮楀鐓庡⒉妞ゃ倕鍊圭换婵堝枈婢跺瞼锛熼梺绋款儐閸ㄥ灝鐣烽幇鏉跨闁挎洍鍋撻柛銊ュ€圭换娑橆啅椤旇崵鍑归梺绋款儜缁绘繈寮诲澶婁紶闁告洦鍓欏▍锝囩磽娴e搫校闁绘濞€瀵顓兼径濠勫幐婵炶揪绲介幉鈥斥枔閺屻儲鈷戠紒瀣閹癸綁鏌涢悩宕囧⒌鐎殿喖顭峰鎾閻橀潧鈧偤鎮峰⿰鍐ら柤楦块哺缁绘繂顫濋鐘插箥闂備礁鎲¢崹顖炲磹閺嶎偀鍋撳鐐
核心提示:预备知识本节内容帮助您为构建 PHP WebDAV 客户机做好准备,关于本系列本教程为系列教程的第 5 部分,开放源码 CMS 入门,第 5 部分: 为 Jakarta Slide 构建 PHP WebDAV 客户机,本系列以 Eclipse、Java™ 技术、Apache Derby 和其他开放源码技术创

预备知识

本节内容帮助您为构建 PHP WebDAV 客户机做好准备。

关于本系列

本教程为系列教程的第 5 部分,本系列以 Eclipse、Java™ 技术、Apache Derby 和其他开放源码技术创建了定制的开放源码内容管理系统(CMS)。在以前的教程中,安装了 Derby、然后在 Derby 中创建 Slide 数据库,并创建了一个适配器,用它为 Derby 实现内容管理存储和检索方法。在这份教程中,将根据这个设置,为基于 Derby 的 PHP 内容管理需求进行构建。

与 Eclipse 配合,还要使用 WebDAV 和其他插件。除 Java 技术之外,还使用了 Jakarta Slide、Apache HTTP Server,当然还有 PHP 和 PHP Eclipse 插件。

关于本教程

本教程面向想创建 PHP WebDAV 客户机的开发人员,用 PHP 访问 Jakarta Slide WebDAV 服务器(或其他 WebDAV 服务器)。通过构建客户端,可了解构建其他应用程序所必需的基本知识,例如由 Jakarta Slide 作为基本支持的 PHP 内容管理系统。

在完成本教程的学习后,您将能够从 PHP 应用程序访问 Slide 或其他任何 WebDAV 服务器(例如,Microsoft® Exchange Server Web 文件夹或 Microsoft Windows® SharePoint® Services Web 文件夹)。通过这种方式,就拥有了一个可以把成百上千用户和文档与文档(内容)和元数据(访问控制列表 [ACL]、资源层次结构等)中央存储捆绑在一起的系统。

本教程覆盖了以下信息和任务:

下载和设置 PHP 环境。

下载和安装 Eclipse 的 PHP 插件。

在 Eclipse 中创建 PHP 客户机项目。

开发和测试针对 Slide 的 PHP 客户机。

回顾和总结。

先决条件

阅读本教程之前,您必须具备基本的 PHP 编程知识和使用 Eclipse 的知识。

要运行本教程中的代码,需要具备以下条件:

PHP 5.1.1 或以上版本

Eclipse 3.0.1 或以上版本

Slide/Tomcat 包 (在第一期教程中已安装)

PHP Eclipse 插件

Apache Tomcat 4.1,如果没有使用上面的 Slide/Tomcat 包,需要安装此程序

请注意: Slide 源不 支持带软件开发包(SDK)1.5 的 Tomcat 5.5。Tomcat 5.0.30 和 SDK 1.4 是代码支持的最新版本。

替代方案 —— 如果没有 Apache、PHP 和 MySql,那么可以使用 XAMPP,这个 Apache 发行版包含 MySQL、PHP 和 Perl。XAMPP 易于安装和使用,只要下载、解压,并按照 XAMPP 安装示例 的说明操作即可。

三个源文件也可从 下载 部分中下载:

class_WebDAVClient.zip

WebDAVClient.zip

Test.zip

系统需求

要运行本教程中的示例,可使用任何版本的 Linux® 或 Windows 操作系统。要求并不严格,所以也可将此客户机与 Slide 放在同一台机器上运行,Slide 是轻量级的,只要能运行 Tomcat,就能运行它。

开始 Eclipse 项目

首先要让 Eclipse 能够创建 PHP WebDAV 客户端。

安装 Eclipse

请注意: 如果在系统上已经运行了 Eclipse 3.0.1 或以上版本,可以跳过这一步。

下载、安装和运行 Eclipse 很容易。只需按以下步骤操作即可:

下载要使用的 Eclipse 版本。本教程基于 Microsoft Windows 上的 Eclipse 3.0.1。

把 .zip 或 .tar 文件释放到选中的目录。

运行 Eclipse.exe (或 UNIX® 上的替代程序)。

如果还没有看过 第 4 份教程 (developerWorks,2006 年 1 月),请现在阅读。需要安装并在 Eclipse 中构建 Slide 2.1 的完整源代码,才能继续学习本教程。

安装 PHP

下载和安装 PHP 也很容易。要安装它,只需按以下步骤进行操作:

下载 PHP 5.1.1 或以上版本。

阅读 PHP 文档,包括 PHP FAQ。

按照 PHP 文档中 Getting Started 部分中的说明进行操作。

下载 Slide 包

在以前的教程中,已经从 Tomcat 包设置了 Slide。可以在本教程中继续使用这个已打包的版本。

设置 PHP eclipse 环境

如果没有学完本系列教程的 第 1 部分,请立刻开始学习,直到按该教程运行了 Slide 2.1。您需要使用这个包,因为本教程不包含 Java 编程的内容。

如果已设置好 PHP eclipse 环境,可以跳到 下一节。 否则,必须正确地创建环境,才能正常使用本教程中的项目。为此,请按照 PHP eclipse Setup PDF 文件或 XAMPP 安装示例 中的说明操作。使用 XAMPP 包可以大大减少开发和测试 PHP 应用程序需要的时间。

由于 XAMPP 包含 Apache、PHP、MySql 和 Perl —— 而且因为 PHP eclipse 拥有 XAMPP 的内置控件,并能把 Eclipse 项目部署到 XAMPP 环境 —— 所以迄今为止,这是最简便的方式。但是,具体选择还是取决于您。

创建 PHP 项目

本节将在 Eclipse 中创建新 PHP 项目。

创建新 PHP 项目

要开始,请单击 File > New > Project > PHP > PHP Project。出现 图 1 所示的 PHP 项目窗口,从这个窗口可以创建 PHP WebDAV 客户机的新项目。

图 1. 创建新 PHP 项目
开放源码 CMS 入门,第 5 部分: 为 Jakarta Slide 构建 PHP WebDAV 客户机

请创建两个新 PHP 文件:一个命名为 WebDAVClient.php,是您的演示页面;另外一个命名为 class_WebDAVClient.php,这是与 WebDAV 服务器(例如 Slide 2.1 服务器)交互的实际的类源文件。

当单击 File > New > PHP File 在 Eclipse 中创建文件时,会得到一个空白的起始文件,如 清单 1 所示。

清单 1. 新 PHP 项目的起始文件

 <?php 
/* 
 * Created on Dec 17, 2005 
 * 
 * To change the template for this generated file go to 
 * Window -> Preferences -> PHPeclipse -> PHP -> 
 * Code Templates 
 */ 
?> 

可以在 Eclipse 的 Preferences 视图中修改这个默认头,这样新文件就可以包含更多信息,例如版权和项目信息。但我们暂时不考虑它。

对于 WebDAVClient.php 文件,请在 ?> 后面输入 Hello World 代码行。这样就可以在 PHP 透视图的 PHP 浏览器视图中查看 Hello World,对文件进行测试。添加的这一行表示现有设置工作正常,可以开始编写代码了。

对于 class_WebDAVClient.php 文件,代码完全放在 ?> 之前,所以 PHP 浏览器视图中无显示。对 class_WebDAVClient.php 作的第一个修改如 清单 2 所示。我们通过这一修改开始编写类代码。

清单 2. 开始编写类代码

<?php 
/* 
 * Created on Dec 17, 2005 
 * 
 * This is the class_WebDAVClient.php source for IBM Tutorial 5 
 * in the open source CMS series. 
 * 
 */ 
class webdavclient { 
 
} 
?> 

所有的类代码都放在 webdavclient 声明的尖括号之间。

关于 WebDAV HTTP 命令的完整列表,请参阅本教程最后的 参考资料 部分。在这份教程中,实现了以下 WebDAV HTTP 命令:

open

ls

mkcol

propfind

get

put

copy

move

delete

options

还实现了两个特定于 Slide 的命令(虽然对于大多数 WebDAV 服务器也适用):

open

ls

其余命令的工作方式或多或少都是类似的,如果学习本教程后您需要编写这些命令,不应存在问题。

第一组方法:open() 和 close()

这一节介绍需在本教程中使用的头两个方法:open() 和 close()。

实现 open() 和 close() 方法

要实现和测试的第一组方法是 open() 方法和它对应的 close() 方法,它们的细节如 清单 3 所示。这些方法直接用 PHP 的套接字方法打开和关闭与 Slide 2.1 WebDAV 服务器的套接字。

函数 open(): 首先发送 open a socket connection 到 _error_log();,然后调用 fsockopen 打开套接字并把 _target 设置到结果。 fsockopen 的参数是局部变量。接下来,把 $this->_target 上的阻塞设置为 true,然后测试 $this->_target 等于 null 还是 error。如果发生了问题,代码把错误记入日志,并返回 false;如果没有问题发生,代码把局部变量 _connection_closed 设置为 false,将成功记入日志,并返回 true。






清单 3. 打开和关闭 WebDAV 服务器套接字的代码

 /** 
 * Opens a socket to a WebDAV server 
 * @return bool true on success. Otherwise false. 
 */ 
function open() { 
  // open a socket 
  $this->_error_log('open a socket connection'); 
  $this->_target = fsockopen ($this->_server, $this- 
 >_port, $this->_error, $this- 
 >_errorstr, $this->_timeout); 
 
  socket_set_blocking($this->_target, true); 
  if (!$this->_target) { 
   $this->_error_log("$this->_errorstr 
 ($this->_error)\n"); 
   return false; 
 } else { 
   $this->_connection_closed = false; 
   $this->_error_log('socket is open: ' . $this->_target); 
   return true; 
 } 
} 
 
/** 
 * Closes the socket. 
 */ 
function close() { 
  $this->_error_log('closing socket ' . $this->_target); 
  $this->_connection_closed = true; 
  fclose($this->_target); 
}         

设置局部变量

在 清单 4 中,设置了局部变量。有些用在 open() 方法中,而有些到后面才会使用。(在后文中使用它们的时候再具体解释)。请把这个代码紧插在 class webdavclient { 代码行之后:

清单 4. 设置局部变量

var $_debug = false; 
var $_target; 
var $_server; 
var $_username = 'root'; 
var $_password; 
var $_protocol = 'HTTP/1.0'; 
var $_port = 8080; 
var $_path ='/files'; 
var $_timeout = 15; 
 
var $_error; 
var $_errorstr; 
var $_agent = 'php class webdavclient $Revision: 1.2 $'; 
var $_crlf = "\r\n"; 
var $_request; 
var $_status; 
var $_parser; 
var $_xmlstr; 
var $_collection; 
var $_list = array(); 
var $_list_element; 
var $_list_element_cdata; 
 
var $_delete = array(); 
var $_delete_element; 
var $_delete_element_cdata; 
 
var $_lock = array(); 
var $_lock_ref; 
var $_lock_rec_cdata; 
 
var $_null = NULL; 
var $_header=''; 
var $_body=''; 
var $_connection_closed = false; 
var $_maxheaderlenth = 1000; 
 

创建局部变量的方法

在 清单 5 中,为这些值创建了一些 set 方法。可能需要在演示页面中做修改。在这个组中,我放了一个构造函数,并把这段代码全都插在局部变量声明之后、open() 方法之前。

清单 5. 为演示页面的值创建 set 方法

/** 
 * Constructor 
 */ 
 function webdavclient() { 
 // noop 
 } 
 
/** 
 * Set the WebDAV server IP address or DNS domain name. 
 * @param string server 
 */ 
function set_server($server) { 
  $this->_server = $server; 
} 
 
/** 
 * Set the TCP port of the Slide WebDAV server. 
 * Default is 8080. 
 * @param int port 
 */ 
function set_port($port) { 
  $this->_port = $port; 
} 
 
/** 
 * Set the user name for authentication 
 * @param string username 
 */ 
function set_username($username) { 
  $this->_username = $username; 
} 
 
/** 
 * Set the password for authentication 
 * @param string pass 
 */ 
function set_password($password) { 
  $this->_password = $password; 
} 
 
/** 
 * Set debug on (1) or off (0). 
 * Produces a lot of debug messages in the Web server's 
 * error log if set to on (1). 
 * The default is off. 
 * @param bool debug 
 */ 
function set_debug($debug) { 
  $this->_debug = $debug; 
} 
 
/** 
 * Set which HTTP protocol will be used. 
 * Value 1 defines that HTTP/1.1 should be used 
 * (Keeps connection to WebDAV server alive.) 
 * Otherwise, HTTP/1.0 will be used. 
 * @param int version 
 */ 
function set_protocol($version) { 
  if ($version == 1) { 
   $this->_protocol = 'HTTP/1.1'; 
  } else { 
   $this->_protocol = 'HTTP/1.0'; 
  } 
  $this->_error_log('HTTP Protocol was set to ' . 
     $this->_protocol); 
} 

测试响应是否来自 WebDAV 服务器

仅仅打开到服务器的套接字是不够的;还需要测试这个服务器是不是 WebDAV 服务器。清单 6 起到了一石二鸟的作用。check_webdav() 方法调用 $this->options() 并看是否有内容返回,如果有内容返回,返回的内容是不是像 WebDAV HTTP 响应。如果是,就返回 true。

清单 6. 判断响应是否来自 WebDAV 服务器

/** 
 * Checks if the server returns a DAV element in the header and when 
 * OPTIONS is supported. 
 * @return bool true if server is webdav server. Otherwise false. 
 */ 
function check_webdav() { 
  $resp = $this->options(); 
  if (!$resp) { 
   return false; 
  } 
  $this->_error_log($resp['header']['DAV']); 
  // check schema 
  if (preg_match('/1,2/', $resp['header']['DAV'])) { 
   return true; 
  } 
  // otherwise return false 
  return false; 
} 
 
/** 
 * Get options from the WebDAV server. 
 * @return false if the server does not return HTTP. 
 */ 
function options() { 
  $this->_unset_header(); 
  $this->_create_request('OPTIONS'); 
  $this->_send(); 
  $this->_get_response(); 
  $response = $this->_process_respond(); 
  // validate the response ... 
  // check http-version 
  if ($response['status']['http-version'] == 'HTTP/1.1' || 
   $response['status']['http-version'] == 'HTTP/1.0') { 
   return $response; 
  } 
  $this->_error_log('Response was not http'); 
  return false; 
} 

显然,WebDAV 需要响应特定于 WebDAV 的请求,例如 options。所以在这里,在 options 中实现了第一个 WebDAV 方法,并用这个方法验证服务器是否为 WebDAV 服务器。

第一个测试:编写演示页面

现在我们已经做好了编写演示页面的准备。通过该页面可以查看效果,执行类并报告类的操作。可用此页面尝试新内容,并测试自己的内容管理应用程序解决方案使用的方法。

连接 WebDAV 服务器

清单 7 显示了使用 webdavclient 类的 PHP 代码,实现了到 WebDAV 服务器的连接,并报告结果。请把这段代码插入到 WebDAVClient.php 源文件的顶部。










清单 7. 头和设置

<?php 
/* 
$Id: WebDAVClient.php,v 1.1 2005/12/10 17:10:18 oliverm Exp $ 
$Author: oliverm $ 
$Date: 2005/12/10 17:10:18 $ 
$Revision: 1.1 $ 
This demonstrates the methods of the webdavclient class. 
 
*/ 
?> 
<html> 
<body> 
<?php 
 
if (!class_exists('webdavclient')) { 
 require('./class_WebDAVClient.php'); 
} 
 
$davclient = new webdavclient(); 
$davclient->set_server('localhost'); 
$davclient->set_port(8080); 
$davclient->set_username('root'); 
$davclient->set_password('MasterP'); 
// use HTTP/1.1 
$davclient->set_protocol(1); 
// enable debugging 
$davclient->set_debug(true); 
 
 
if (!$davclient->open()) { 
 print 'Error: could not open WebDAV connection'; 
 exit; 
} 
 
// check if server supports webdav rfc 2518 
if (!$davclient->check_webdav()) { 
 print 'Error: server does not support webdav or 
 user/password may be wrong'; 
 
 exit; 
} else { 
 print 'Success: server does support webdav 
 and user/password is accepted!'; 
 
 
} 
?> 
</body> 
</html> 
         

现在请确保 Slide 包正在运行。(应当在类似于 http://localhost:8080/slide 这样的 URL 上。)请测试能够通过浏览器、以将在 WebDAVClient.php 中使用的用户名和口令直接连接。了解 Slide 正在运行,而且您能够连接到它之后,请检验在 WebDAVClient.php 中设置了相同的信息并运行它。Eclipse 的 PHP 透视图中的 PHP 浏览器应当工作正常,所以您将看到 Success: server does support WebDAV, and user/password is accepted!。

就象我经常告诉我的程序员的“picollo passo”或“小步走”。在这里,您所做的是连接服务器和运行测试的最少工作。现在,可以在此基础之上构建了。如果这一部分无法正常工作,请查看它哪里出了错。

列出服务器根的内容

下一步是列出 Slide 服务器根的内容。清单 8 显示了类的方法 list (有些人可能喜欢用 ls),这个方法到 Slide 上获取位于 / 的集合的内容清单。

清单 8. ls 方法

/** 
  * Public method ls 
  * 
  * Gets the collection list from the WebDAV server into an 
  * array using PROPFIND 
  * @param string path 
  * @return array list, false on error 
  */ 
  function ls($path) { 
 
   if (trim($path) == '') { 
     $this->_error_log('Missing a path in method ls'); 
     return false; 
   } 
   $this->_path = $path; 
 
   $this->_unset_header(); 
   $this->_create_request('GET'); 
   $this->_send(); 
   $this->_error_log('ls()'); 
   $this->_get_response(); 
   $response = $this->_process_respond(); 
   $this->_error_log('VVVVVVV response[status]\ 
      [http-version]=VVVVVV'); 
   $this->_error_log($response['status']['http-version']); 
   // validate the response ... (only basic validation) 
   // check http-version 
   if ($response['status']['http-version'] == 'HTTP/1.1' || 
     $response['status']['http-version'] == 'HTTP/1.0') { 
     // seems to be http ... proceed 
     $this->_error_log('status::status-code'); 
     $this->_error_log($response['status']['status-code']); 
     // We expect a 200 status code 
     
     if (strcmp($response['status']\ 
      ['status-code'],'200') == 0 ) { 
      $this->_error_log('this->_body='); 
       $this->_error_log($this->_body); 
     
      return $this->_body; 
     } else { 
      $this->_error_log('Missing Content-Type: \ 
          text/xml header in response!!'); 
      return false; 
     } 
   } 
 
   // response was not http 
   $this->_error_log('Error in ls: response was not HTTP'); 
   return false; 
  } 
 

现在,在 WebDAVClient.php 页面中,调用类的 list 方法并显示结果。清单 9 显示了这个页面添加的内容。

清单 9. 列表以测试 ls 方法

$contents = $davclient->ls('/slide/files'); 
?> 
<h1>WebDAVClient Demo:</h1><p> 
Using method webdavclient::ls('/slide/files') 
 to get a listing of dir '/slide/files':<br> 
 
(*Note this snapshot's links are dereferenced and won't work, however 
you can follow this link to the same page... 
 <a href="http://localhost:8080/slide/files/" 
 >/slide/files/</a> 
 
<table summary="ls" border="1"> 
<tr> 
<th>GET /files</th> 
<tr> 
<td> 
<?php 
print $contents 
?> 
</td> 
</tr> 
</table> 

刷新页面。PHP 浏览器现在应当显示如 图 2 所示的内容。

图 2. 新演示页面
开放源码 CMS 入门,第 5 部分: 为 Jakarta Slide 构建 PHP WebDAV 客户机

Slide 用简单的 HTTP 接口处理 GET 命令,Slide servlet 查看普通的旧 GET 并构建带有链接的 HTML 页面。因为要从服务器到服务器,而且这个客户机不是浏览器,所以链接被禁用,并与服务器的上下文相关,所以在从浏览器查看 WebDAVClient.php 时它们不会工作。

清单 10 显示了与其他方法共享的一些工具方法。

清单 10. getInfo 方法

/** 
  * Public method getInfo 
  * 
  * Gets path information from the WebDAV server for one element 
  * @param string path 
  * @return array dirinfo. false on error 
  */ 
  function getInfo($path) { 
 
   // split path by last "/" 
   $path = rtrim($path, "/"); 
   $item = basename($path); 
   $dir = dirname($path); 
 
   $list = $this->list($dir); 
 
   // be sure it is an array 
   if (is_array($list)) { 
     foreach($list as $e) { 
 
      $fullpath = urldecode($e['href']); 
      $filename = basename($fullpath); 
 
      if ($filename == $item && $filename != 
  "" and $fullpath != $dir."/") { 
        return $e; 
      } 
     } 
   } 
   return false; 
  } 
 
 /** 
  * Public method is_file 
  * 
  * Test whether a path points to a file 
  * @param string path 
  * @return bool true or false 
  */ 
  function is_file($path) { 
 
   $item = $this->getInfo($path); 
 
   if ($item === false) { 
     return false; 
   } else { 
     return ($item['resourcetype'] != 'collection'); 
   } 
  } 
 

mkcol、get 和 put 方法

这一节介绍了如何在 WebDAV 客户机中使用 mkcol、get 和 put 方法。

mkcol 方法

接下来添加 mkcol 方法,它在 Slide 仓库中创建集合(即,文件夹或目录)。WebDAV 规范毕竟是 HTTP 的扩展,所以可以预见,HTTP 响应代码是类似的。mkcol HTTP 请求返回的响应码带有一些解释性文本。WebDAV 规范(RFC 2518)把代码分成以下几种:

201(已经创建):集合或结构化资源已经完整创建。

403(禁止):这个错误表示至少出现了以下两种情况之一:1)服务器不允许在其名称空间的指定位置创建集合;2)所请求的统一资源标识符(URI)的父集合存在,但是不接受成员。

405(方法不允许): MKCOL 命令只能在已经删除/不存在的资源上执行。

409(冲突):只在一个或多个中间集合已经创建之后,在请求的 URI 上才能创建某个集合。

415(不支持的媒体类型): 服务器不支持请求的实体类型。

507(存储空间不足): 在这个方法 执行之后,资源没有足够的空间记录资源的状态。

清单 11 显示了 mkcol() 方法,它相当简单。

清单 11. mkcol() 方法

/** 
 * Public method mkcol 
 * 
 * Creates a new collection/folder on a WebDAV server 
 * @param string path 
 * @return int status code received as response 
 */ 
function mkcol($path) { 
  $this->_path = $path; 
  $this->_unset_header(); 
  $this->_create_request('MKCOL'); 
  $this->_send(); 
  $this->_get_response(); 
  $response = $this->_process_respond(); 
  // validate the response ... 
  // check http-version 
  if ($response['status']['http-version'] == 'HTTP/1.1' || 
   $response['status']['http-version'] == 'HTTP/1.0') { 
   /* seems to be http ... to proceed, just return the 
   response status-code */ 
   return $response['status']['status-code']; 
  } 
} 

清单 12 显示了在类的内部使用的一些用来创建部分 WebDAV 请求和响应的专用方法。

清单 12. _header 和其他方法

/** 
  * Private method _header 
  * 
  * extends class var array _request  
  * @param string string 
  * @access private 
  */ 
  function _header($string) { 
   $this->_request[] = $string; 
  } 
 
 /** 
  * Private method _unset_header 
  * 
  * unsets class var array _request  
  * @access private 
  */ 
 
  function _unset_header() { 
   unset($this->_request); 
  } 
 
 /** 
  * Private method _create_request 
  * 
  * creates by using private method _header 
  * an general request header. 
  * @param string method 
  * @access private 
  */ 
  function _create_request($method) { 
   $request = ''; 
   $this->_header(sprintf('%s %s %s', 
 $method, $this->_path, $this->_protocol)); 
 
   $this->_header(sprintf('Host: %s', $this->_server)); 
   $this->_header(sprintf('User-Agent: %s', $this->_agent)); 
   $this->_header(sprintf('Authorization: Basic %s', 
    base64_encode("$this->_username:$this->_password"))); 
 
  } 
 
 /** 
  * Private method _send 
  * 
  * Sends a ready formed HTTP/WebDAV request to 
  * the WebDAV server. 
  * @access private 
  */ 
  function _send() { 
   // check if stream is declared to be open 
   // only logical check we are not sure 
 //if socket is really still open ... 
 
   if ($this->_connection_closed) { 
     // reopen it 
     // be sure to close the open socket. 
     $this->close(); 
     $this->_reopen(); 
   } 
 
   // convert array to string 
   $buffer = implode("\r\n", $this->_request); 
   $buffer .= "\r\n\r\n"; 
   $this->_error_log($buffer); 
   fputs($this->_target, $buffer); 
  } 
 
 /** 
  * Private method _get_response 
  * 
  * Read the response of the WebDAV server. 
  * Stores data into class vars _header for the header data and 
  * _body for the rest of the response. 
  * This routine is the weakest part of this class, because it 
  * depends how PHP handles a socket stream. 
  * If the stream is blocked for some reason, PHP is blocked 
  * as well. 
  * @access private 
  */ 
  function _get_response() { 
   //see the full source for this and other methods 
   //in the downloadable .zip file for this tutorial. 
  } 
 

get 方法

get() 方法如 清单 13 所示,用来返回一个缓冲区,里面添加了内容服务器上的资源 —— 即文件。Slide 检测 get() 得到的是资源而不是集合。

清单 13. get() 方法

/** 
  * Public method get 
  * 
  * Gets a file from a WebDAV collection. 
  * @param string path, string &buffer 
  * @return status code and &$buffer (by reference) with 
  * response data from server on success. False on error. 
  */ 
  function get($path, &$buffer) { 
   $this->_path = $path; 
   $this->_unset_header(); 
   $this->_create_request('GET'); 
   $this->_send(); 
   $this->_get_response(); 
   $response = $this->_process_respond(); 
 
   // validate the response 
   // check http-version 
   if ($response['status']['http-version'] == 'HTTP/1.1' || 
     $response['status']['http-version'] == 'HTTP/1.0') { 
     // seems to be http ... proceed 
     // We expect a 200 code 
     if ($response['status']['status-code'] == 200 ) { 
      $this->_error_log('returning buffer with ' . 
  strlen($response['body']) . ' bytes.'); 
      $buffer = $response['body']; 
     } 
     return $response['status']['status-code']; 
    } 
    // ups: no http status was returned ? 
    return false; 
  } 

清单 14 有两个重要内容。_get_response() 方法处理来自 WebDAV 服务器的响应,检测响应类型(简单头、XML 响应体或字节内容),并把它全部分解成可用的组件。

清单 14. get_response() 方法

/** 
  * Private method _get_response 
  * 
  * Read the response of the WebDAV server. 
  * Stores data into class vars _header for the header data and 
  * _body for the rest of the response. 
  * This routine is not bulletproof, because it depends on how PHP 
  * handles a socket stream. 
  * If the stream is blocked for some reason, 
  * PHP is blocked as well. 
  * @access private 
  */ 
  function _get_response() { 
   $this->_error_log('_get_response()'); 
    
   $buffer = ''; 
   $header = ''; 
   // attention: do not make max_chunk_size too big.... 
   $max_chunk_size = 8192; 
   // be sure we got a open resource 
   if (! $this->_target) { 
     $this->_error_log('socket is not open. 
 Can not process response'); 
 
     return false; 
   } 
 
   // read stream one byte by another until http header ends 
   $i = 0; 
   do { 
     $header.=fread($this->_target,1); 
     $i++; 
   } while (!preg_match('/\\r\\n\\r\\n$/',$header) 
 && $i < $this->_maxheaderlenth); 
 
   $this->_error_log('************ response 
 $header***********'); 
 
   $this->_error_log($header); 
 
   if (preg_match('/Connection: close\\r\\n/', $header)) { 
     // This says that the server will close 
  //connection at the end of this stream. 
     // Therefore we need to reopen the socket 
     //before sending the next request... 
     $this->_error_log('Connection: close found'); 
     $this->_connection_closed = true; 
   } 
   // check how to get the data on socket stream 
   // chunked or content-length (HTTP/1.1) or 
   // one block until feof is received (HTTP/1.0) 
    
 //download the source to see the rest of this method. 
  } 
 
 
 
  // -------------------------------------------------------------------------- 
  // private method _process_respond ... 
  // analyze the response from server 
  //and divide into header and body part 
  // returns an array filled with components 
 /** 
  * Private method _process_respond 
  * 
  * Processes the WebDAV server response, detects its 
  * components (header, body), 
  * and returns data array structure. 
  * @return array ret_struct 
  * @access private 
  */ 
  function _process_respond() { 
   $lines = explode("\r\n", $this->_header); 
   $header_done = false; 
   // $this->_error_log($this->_buffer); 
   // First line should be an http status line 
   //(see http://www.w3.org/Protocols/rfc2616/ 
 // rfc2616-sec6.html#sec6) 
 
   // Format is: HTTP-Version SP Status-Code SP Reason-Phrase CRLF 
   list($ret_struct['status']['http-version'], 
       $ret_struct['status']['status-code'], 
       $ret_struct['status']['reason-phrase']) = 
  explode(' ', $lines[0],3); 
 
 
   // print "HTTP Version: '$http_version' Status-Code: 
 // '$status_code' Reason Phrase: '$reason_phrase'<br>"; 
   // get the response header fields 
   // See http://www.w3.org/Protocols/rfc2616/ 
 // rfc2616-sec6.html#sec6 
 
   for($i=1; $i<count($lines); $i++) { 
     if (rtrim($lines[$i]) == '' && !$header_done) { 
      $header_done = true; 
      // print "--- response header end ---<br>"; 
 
     } 
     if (!$header_done ) { 
      // store all found headers in array ... 
      list($fieldname, $fieldvalue) = explode(':', $lines[$i]); 
      // check if this header was already set 
 //(apache 2.0 webdav module does this....). 
      // If so we add the value to the end of 
 //the fieldvalue, separated by a comma... 
      if (! $ret_struct['header'][$fieldname]) { 
        $ret_struct['header'][$fieldname] = trim($fieldvalue); 
      } else { 
       $ret_struct['header'][$fieldname] .= ',' . 
  trim($fieldvalue); 
 
      } 
     } 
   } 
   // print 'string len of response_body:'. 
 //  strlen($response_body); 
   // print '[' . htmlentities($response_body) . ']'; 
   $ret_struct['body'] = $this->_body; 
   return $ret_struct; 
  } 
         

在 WebDAVClient.php 中尝试所有方法

WebDAVClient.php 页面应当尝试 mkcol、 get 和 put ,以及 copy、move 和 delete 的所有方法。清单 15 显示了执行这些方法的其余代码。在每种情况下,方法都接受一个或两个参数,并返回一个状态码。对于 PHP 程序来说,这段代码并不精妙,但我们目的是尝试练习 Client 类的方法。

清单 15. mkcol() 方法和移动一些文件

Create a new collection (Folder) using method webdavclient::mkcol() 
<?php 
$perm_folder = '/slide/files/permanent/'; 
print '<br>creating collection ' . 
 $perm_folder .' ...<br>'; 
 
$http_status = $davclient->mkcol($perm_folder); 
print 'Slide WebDAV server returns ' . $http_status . '<br>'; 
 
$test_folder = '/slide/files/IBM_Tutorial_5'; 
print '<br>creating collection ' . 
 $test_folder .' ...<br>'; 
 
$http_status = $davclient->mkcol($test_folder); 
print 'Slide WebDAV server returns ' . $http_status . '<br>'; 
 
print 'removing collection just created using 
 method webdavclient::delete ...<br>'; 
 
$http_status_array = $davclient->delete($test_folder); 
print 'Slide WebDAV server returns ' . 
 $http_status_array['status'] . '<br>'; 
 
print 'see what\'s happening when we try to 
 delete the same nonexistent collection again....<br>'; 
 
$http_status_array = $davclient->delete($test_folder); 
print 'WebDAV server returns '. 
 $http_status_array['status'] . '<br>'; 
 
 
print 'see what\'s happening when we try to 
 delete an existing locked collection....<br>'; 
 
$http_status_array = $davclient->delete('/packages.txt'); 
print 'WebDAV server returns ' . 
 $http_status_array['status'] . '<br>'; 
 
print 'create a second collection ...' . 
 $test_folder . '<br>'; 
$http_status = $davclient->mkcol($test_folder); 
print 'WebDAV server returns ' . $http_status . '<br>'; 
 
// put a file to WebDAV collection 
$filename = '/temp/test.txt'; 
print 'put the file ' . $filename . ' using 
 webdavclient::put into collection...<br>'; 
 
$handle = fopen ($filename, 'r'); 
$contents = fread ($handle, filesize ($filename)); 
fclose ($handle); 
$target_path = $test_folder . '/test.txt'; 
$http_status = $davclient->put($target_path,$contents); 
print 'WebDAV server returns ' . $http_status .'<br>'; 
 
$filename = '/temp/test.jpg'; 
print 'Test second put method...<br>'; 
$target_path = $test_folder . '/test.jpg'; 
$http_status = $davclient->putf($target_path, $filename); 
print 'WebDAV server returns ' . $http_status . '<br>'; 
 
print 'get file just put'; 
$http_status = $davclient->get($test_folder . 
 '/test.jpg', $buffer); 
print 'WebDAV server returns ' . $http_status . '. 
 Buffer is filled with ' . strlen($buffer). 
 ' Bytes.<br>'; 
 
 
 
print 'use method webdavclient::copy to create a 
 copy of file ' . $target_path . ' the 
 WebDAV server<br>'; 
 
$new_copy_target = '/test[2].jpg'; 
$http_status = $davclient->copyf( 
 $target_path, $new_copy_target, true); 
 
print 'WebDAV server returns ' . $http_status . '<br>'; 
 
print 'use method webdavclient::copy to create 
 a copy of collection ' . $test_folder . 
 ' the WebDAV server<br>'; 
 
$new_copy_target = '/copy_of_IBM_Tutorial_5'; 
$http_status = $davclient->copyc($test_folder, 
 $new_copy_target, true); 
 
print 'WebDAV server returns ' . $http_status . '<br>'; 
 
print 'move/rename a file in a collection<br>'; 
$new_target_path = $test_folder . '/test_renamed.jpg'; 
$http_status = $davclient->move($target_path, 
 $new_target_path, true); 
 
print 'WebDAV server returns ' . $http_status . '<br>'; 
 
print 'move/rename a collection<br>'; 
$new_target_folder = $test_folder + '_renamed'; 
$http_status = $davclient->move($test_folder, 
 $new_target_folder, true); 
 
print 'Slide WebDAV server returns ' .  
 $http_status . '<br>'; 
 
print 'remove/delete the moved collection ' . 
 $new_target_folder . '<br>'; 
 
$http_status_array = $davclient-> 
delete($new_target_folder); 
print 'Slide WebDAV server returns ' . 
 $http_status_array['status'] . '<br>'; 
 
 
$davclient->close(); 
flush(); 
?> 
</body> 
<html> 
        

上载到 Slide 服务器

现在要在 WebDAVClient.php 中用最后一种主要方法把文件 put 或上载到 Slide 服务器。

使用 PUT 方法上载文件

请注意在完整的源代码中,我创建了两个方法,用不同的方式处理文件和集合。使用 putf() 和 getf() 方法时,我想处理文件名而不是缓冲(字节数组),但是其他都是相同的。我只是用文件名创建读或写的流。

清单 16 中的 put() 方法处理称为 $data 的缓冲区。这个方法相当简单,而且套接字的处理方式也与文件资源非常类似,在 send() 创建了请求并把请求返回 _target 之后,用 fputs() 处理 _target。







清单 16. put() 方法

/** 
  * Public method put 
  * 
  * Puts a file into a collection. 
  *  Data is put as one chunk! 
  * @param string path, string data 
  * @return int status-code read from webdavserver. False on error. 
  */ 
  function put($path, $data ) { 
   $this->_path = $path; 
   $this->_unset_header(); 
   $this->_create_request('PUT'); 
   // add more needed header information ... 
   $this->_header('Content-length: ' . strlen($data)); 
   $this->_header('Content-type: application/octet-stream'); 
   // send header 
   $this->_send(); 
   // send the rest (data) 
   fputs($this->_target, $data); 
   $this->_get_response(); 
   $response = $this->_process_respond(); 
 
   // validate the response 
   // check http-version 
   if ($response['status']['http-version'] == 'HTTP/1.1' || 
     $response['status']['http-version'] == 'HTTP/1.0') { 
     // seems to be http ... proceed 
     // We expect a 200 or 204 status code 
     // see rfc 2068 - 9.6 PUT... 
     // print 'http ok<br>'; 
     return $response['status']['status-code']; 
    } 
    // ups: no http status was returned ? 
    return false; 
  } 
         

用 copy 和 move 方法进行文件传输

清单 17 显示了在 WebDAVClient.php 演示中使用的最后一种主要方法:copy(两种风格)和 move。至此,您应已注意到,所有方法的元语都是类似的:方法接受一组 URI 字符串,完成某些操作,然后返回一个状态码。

清单 17. copy 和 move 方法

/** 
  * Public method copyf 
  * 
  * Copy a file on the WebDAV server 
  * Duplicates a file on the WebDAV server (serverside). 
  * All the work is done on the WebDAV server. If you 
 * set param overwrite as true, 
 * the target will be overwritten. 
 * 
 * @param string src_path, string dest_path, bool overwrite 
 * @return int status code (look at rfc 2518). false on error. 
 */ 
 function copyf($src_path, $dst_path, $overwrite) { 
 $this->_path = $src_path; 
 $this->_unset_header(); 
 $this->_create_request('COPY'); 
 $this->_header(sprintf('Destination: http://%s%s', 
 $this->_server, $dst_path)); 
 
 if ($overwrite) { 
  $this->_header('Overwrite: T'); 
 } else { 
  $this->_header('Overwrite: F'); 
 } 
 $this->_header(''); 
 $this->_send(); 
 $this->_get_response(); 
 $response = $this->_process_respond(); 
 // validate the response ... 
 // check http-version 
 if ($response['status']['http-version'] == 'HTTP/1.1' || 
  $response['status']['http-version'] == 'HTTP/1.0') { 
  /* seems to be http ... proceed */ 
  return $response['status']['status-code']; 
 } 
 return false; 
 } 
 
/** 
 * Public method copyc 
 * 
 * Copy a collection on the WebDAV server 
 * Duplicates a collection on the WebDAV server (serverside). 
 * All work is done on the WebDAV server. If you set param 
 * overwrite as true, 
 * the target will be overwritten. 
 * 
 * @param string src_path, string dest_path, bool overwrite 
 * @return int status code (look at rfc 2518). false on error. 
 */ 
 function copyc($src_path, $dst_path, $overwrite) { 
 $this->_path = $src_path; 
 $this->_unset_header(); 
 $this->_create_request('COPY'); 
 $this->_header(sprintf('Destination: 
 http://%s%s', $this->_server, $dst_path)); 
 
 $this->_header('Depth: Infinity'); 
 
 $xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n"; 
 $xml .= "<d:propertybehavior xmlns:d=\"DAV:\">\r\n"; 
 $xml .= " <d:keepalive>*</d:keepalive>\r\n"; 
 $xml .= "</d:propertybehavior>\r\n"; 
 
 $this->_header('Content-length: ' . strlen($xml)); 
 $this->_header('Content-type: text/xml'); 
 $this->_send(); 
 // send also xml 
 fputs($this->_target, $xml); 
 $this->_get_response(); 
 $response = $this->_process_respond(); 
 // validate the response ... 
 // check http-version 
 if ($response['status']['http-version'] == 'HTTP/1.1' || 
  $response['status']['http-version'] == 'HTTP/1.0') { 
  /* seems to be http ... proceed */ 
  return $response['status']['status-code']; 
 } 
 return false; 
 } 
 
 /** 
 * Public method move 
 * 
 * Move a file or collection on the WebDAV server (serverside) 
 * If you set param overwrite as true, the target 
 * will be overwritten. 
 * 
 * @param string src_path, string dest_path, bool overwrite 
 * @return int status code (look at rfc 2518). false on error. 
 */ 
 // ------------------------------------------------------------- 
 // public method move 
 // move/rename a file/collection on webdav server 
 function move($src_path,$dst_path, $overwrite) { 
 
 $this->_path = $src_path; 
 $this->_unset_header(); 
 
 $this->_create_request('MOVE'); 
 $this->_header(sprintf('Destination: 
  http://%s%s', $this->_server, $dst_path)); 
 
 if ($overwrite) { 
  $this->_header('Overwrite: T'); 
 } else { 
  $this->_header('Overwrite: F'); 
 } 
 $this->_header(''); 
 
 $this->_send(); 
 $this->_get_response(); 
 $response = $this->_process_respond(); 
 // validate the response ... 
 // check http-version 
 if ($response['status']['http-version'] == 'HTTP/1.1' || 
  $response['status']['http-version'] == 'HTTP/1.0') { 
  /* seems to be http ... proceed */ 
  return $response['status']['status-code']; 
 } 
 return false; 
 } 
 

全部状态码如下:

201(已创建):源资源已经成功删除,新资源已经在目标创建。

204(没有内容):源资源已成功移动到已有目标资源上。

403(禁止):源和目标 URI 是相同的。

409(冲突):资源不能在目标上创建 —— 除非创建了一个或多个中间资源。

412(预处理失败):服务器不能维护 propertybehavior XML 元素列出的属性的“活动性”,或 Overwrite 头为 F,而目标源的状态是非 NULL。

423(锁定):源或目标资源被锁定。

502(错误网关):当目标在在另一台服务器上,而目标服务器拒绝接受资源时,可能出现这个错误。

201(已经创建):集合或结构化资源已经完全创建。

403(禁止): 这个错误表示至少以下一种情况:1)服务器不允许在其名称空间的指定位置创建集合;2)请求的 URI 的父集合存在,但是不接受成员。

405(方法不允许): mkcol 方法只能在已经删除或不存在的资源上执行。

409(冲突):在请求的 URI 上不能创建集合 —— 除非创建了一个或多个中间集合。

415(不支持的媒体类型):服务器不支持主体的请求类型。

507(存储空间不足):方法执行之后,资源没有足够的空间记录资源的状态。

未来

在这一节中,您将了解可用刚创建的 PHPWebDAV 客户机实现哪些目的。

WebDAV 客户机的未来

那么接下来该做什么?用这个 PHP WebDAVClient 能做什么?有什么 PHP 应用程序需要保存文件么?该怎么保存不同版本的文件呢?如何保存带有元数据属性的文件呢?想不想扫描到来的发票,用光学字符识别设备(OCR)来扫描它,根据扫描创建发票,并把它们一起保存在 XML 中呢?

我们只是浅显地介绍了 Slide 能实现的目的,这个客户机应当随着时间而成长,满足您的需求。Slide 在保存和检索 XML 文档方面表现出色,可以把元数据属性保存为 XML 并把它们很好地绑定到资源或相等的集合上。

WebDAVClient 类最明显的应用就是用您了解的语言把 PHP 内容管理构建到 Web 站点。可以运行 Slide/Tomcat 包而完全不涉及 Java。利用 PHP 技能就可以构建特性全面的 CMS,而且 还能拥有与 Microsoft Office 或其他 WebDAV 敏感的应用程序集成的 WebDAV 能力。

结束语

PHP 可以通过套接字连接和 HTTP 与任何 WebDAV 服务器对话。了解 WebDAV 规范后,在本教程中编写的 WebDAVClient 类就能简化构建您自己的 PHP 应用程序时要编写的其他代码。可以是需要保存和检索资源资源的任何 PHP 应用程序。这些资源不一定是充满页面和图片的站点意义上的内容 —— 但可以是。我敢确定,您希望以这个客户机类为起点,进一步展开学习,扩展它的一些方法,添加一些自己的方法。

在本系列的下一篇教程中,我们将使用另一种开放源码语言与 Slide 相配合:Python。Python 在某些环境下独具优势,没有理由不让 Python 开发人员与 PHP 开发人员或 Java 开发人员具备相同的能力,以利用 Jakarta Slide 或其他任何 WebDAV 服务器。那么,咱们下回见!

下载

描述名字大小下载方法
WebDAV client class for this tutorialclass_WebDAVClient.zip10KBHTTP
Display page for exercising the class fileWebDAVClient.zip12KBHTTP
Test file for this tutorialTest.zip1KBHTTP

Tags:开放 源码 CMS

编辑录入:爽爽 [复制链接] [打 印]
[]
  • 好
  • 好的评价 如果觉得好,就请您
      0%(0)
  • 差
  • 差的评价 如果觉得差,就请您
      0%(0)
赞助商链接