FTP文件操作。

来源:互联网 发布:加内特各项数据总数 编辑:程序博客网 时间:2024/06/03 22:17

VC中实现FTP功能

----要联接到FTP服务器,需要两个步骤,首先必须创建一个CInternetSession对象,用类CInterSession创建并初始化一个或几个同时存在的Internet会话(session),并描述与代理服务器的连接(如果有必要的话),如果在程序运行期间需要保持与Internet的连接,可以创建一个CInternetSession对象作为类CWinApp的成员。
- F: M6 m4 }3 {5 f1 `+ c) f3 R----MFC中的类CFtpConnection管理我们与Internet服务器的连接,并直接操作服务器上的目录和文件,FTP是MFC的WinInet支持的三个Internet功能之一,我们需要先创建一个CInternetSession实例和一个CFtpConnection对象就可以实现和一个FTP服务器的通信,我们不需要直接创建CFtpConnection对象,而是通过调用CInternetSession::GetFtpConnection来完成这项工作。它创建CFtpConnection对象并返回一个指向该对象的指针。
+ j: t7 u' t* ]" U, q& r" YFtp连接类的信息
( }) M. ]  A7 U, R3 y9 C) a8 k  H---- 下面我们简要介绍连接类的信息 . x$ D! ]/ |5 D! m' Y, y8 P/ A
CInternetSession对象
0 Y3 G% |2 ?  S. E----CInternetSession(LPCTSTR pstrAgent,DWORD dwConText ,DWORDdwAccessType,LPCTSTR pstrProxyName,LPCTSTR pstrProxyBypass,DWORDdwFlags); 8 N/ e+ r, {9 f, M8 b6 W" k
----在创建CInternetSession对象时调用这个成员函数,CInternetSession是应用程序第一个要调用的Internet函数,它将创始化内部数据结构,以备将来在应用程序中调用。如果dwFlags包含INTERNET_FLAG_ASYNC,那末从这个句柄派生的所有的句柄,在状态回调例程注冊之前,都会出现异步状态。如果沒有打开Internet连接,CInternetSession就会抛出一个例外,AfxThorowInternetException。 " k9 I5 W: m# y) Y
GetFtpConnection()函数 5 V. q8 a) r2 K7 Y
---- CFtpConnection* CIternetSession::GetFtpConnection(LPCTSTRpstrServer,LPCTSTR pstrUserName,LPCTSTR pstrPassword,INTERNET_PORTnPort,BOOL bPassive); 4 C) ^( y$ B) /, f0 J$ h% i
----调用这个函数建立一个FTP连接,并获得一个指向CFtpConnection对象的指针,GetFtpConnection连接到一个FTP服务器,创建并返回指向CFtpConnection对象的指针,它不在服务器上进行任何操作。如果打算读写文件,必须进行分步操作。关于查找,打开和读/写文件的信息需参考CFtpConnection和CFtpFileFind类。 / T  ~6 X+ M4 @/ P
---- 对这个函数的调用返回一个指向CFtpConnection对象的指针。如果调用失败,检查抛出的CInternetException对象,就可以确定失败的原因。 8 B6 x. Q  |  d- |. H) F
GetFile()函数
9 U8 T9 Q% ~3 z0 M---- BOOLGetFile(LPCTSTR pstrRemoteFile,LPCTSTR pstrLocalFile,BOOL bFailExists,DWORD dwAttributes,DWORD dwFlags,DWORD dwContext); 7 c  a" x& o& e+ m
----调用这个成员函数,可以从FTP服务器取得文件,并且把文件保存在本地机器上。GetFile()函数是一个比较高级的例程,它可以处理所有有关从FTP服务器读文件,以及把文件存放在本地机器上的工作。如果dwFlags为FILE_TRANSFER_TYPE_ASCII,文件数据的传输也会把控制和格式符转化为Windows中的等阶符号。默认的传输模式是二进制模式,文件会以和服务器上相同的格式被下载。 - F( ]- m- P$ g, S( Z
---- pstrRemoteFile和pstrLocalFile可以是相对于当前目录的部分文件名,也可以是全文件名,在这两个名字中间,都既可以用反斜杠(/)或者正斜杠(/)来作为文件名的目录分隔符,GetFile()在使用前会把目录分隔符转化为适当的字符。
- u: N5 W+ /; C6 E; x; h" z----可以用自己选择的值来取代dwContext默认的值,设置为上下文标识符与CFtpConnection对象的定位操作有关,这个操作由CFtpConnection中的CInternetSession对象创建。返回给CInternetSession::OnStatusCallBack的值指出了所标识操作的状态。 & V, _# u1 V7 O- c
---- 如果调用成功,函数的返回为非0,否则返回0,如果调用失败,可以调用Win32函数GetLastError(),确认出错的原因。 . V. y- A( {# X* u# ?
PutFile()函数
* G0 r' r: m- e: w) O0 `$ f---- BOOL PutFile(LPCTSTR pstrLocalFile, LPCTSTR pstrRemoveFile ,DWORD dwFlags, DWORD dwContext);
9 G, ]1 l- z3 m& B$ ^8 A+ M----调用这个成员函数可以把文件保存到FTP服务器。PutFile()函数是一个比较高级的例程,它可以处理有关把文件存放到服务器上的工作。只发送数据,或要严格控制文件传输的应用程序,应该调用OpenFile和CInternet::Write。利用自己选择的值来取代dwContext默认的值,设置为上下文标识符,上下文标识符是CInternetSession对象创建的CFtpConnection对象的特定操作有关,这个值返回给CInternetSession::OnStateCallBack,从而把操作的状态通报给它所标识的上下文。
7 F. `  c# x8 Y' B---- 如果调用成功,函数的返回为非0,否则返回0,如果调用失败,可以调用Win32函数GetLastError(),确认出错的原因。 1 `2 E* Y- e: h& z* ~
连接到FTP站点
+ i. ^' [2 [' c9 e) e3 d# }3 L---- 建立连接到ftp.microsoft.com的程序,它是一个单文档程序。并且连接由视图类的构造函数完成。

建立单文档程序ftp
% d3 z2 y  {8 c" Y6 Y在ftpview.h中加入包含#include  
  y; Y# j% Y' W( b4 s在ftpview.h中添加如下的成员变量 ' N% ~5 v9 H: m( W! ]) Y- e5 [1 j9 ]
public:
" s, s8 N1 a6 Q8 /% S% kCInternetSession *m_pInetSession;
$ D( q8 h, {3 o# l0 g& _$ FCFtpConnection *m_pFtpConnection;
- m6 |' A- b) k* R" `  R$ }; Z在ftpview.cpp中的ftpview构造函数中加入下面的代码 2 l3 h- E# ]: C) ~
CFtpView::CFtpView()
. K9 @) G, T& h6 `& X{ " ?# L& R; G9 I; n; H. i
m_pInetSession=new CInternetSession
/ q' z! ?! f) o, S: z(AfxGetAppName(),1,
0 j/ W2 p, I: R3 k" `5 e; v# pPRE_CONFIG_INTERNET_ACCESS); ) R) |' Z+ B/ d$ |/ a( ]
try
2 J& W# r" J/ j7 q3 X{ $ B5 i. b$ i1 [, /) Z; Q0 a
m_pFtpConnection=m_pInetSession->
) o3 Z. k3 h% E) G/ IGetFtpConnection("FTP.MICROSOFT.COM");   b1 ^" A" W' p" L4 i/ E5 E
}
3 W6 a/ [$ S8 E4 M# O3 vcatch(CInternetException *pEx) : N( ~. l6 r% /2 r
{
- ?6 d2 Q' X( i" v" {! K# F+ [: DTCHAR szError[1024]; 4 n, t4 e1 V; C" j
if(pEx->GetErrorMessage(szError,1024)) 7 Q8 p" d& ^8 X3 a2 e0 j
AfxMessageBox(szError); $ ^0 Z/ [- v5 E! T- @+ ~
else
8 D3 n4 i: P- ~$ ]AfxMessageBox("There was an exception");
8 Y0 q! D- @& G& e  GpEx->Delete(); # n3 k4 ]' x. [& m; t+ ~
m_pFtpConnection=NULL;
8 S3 {* E* D' t} % /  ?0 H% M6 x9 n. K
}
! /0 c2 j3 E# P7 E- j# ^; B* s4 q在ftpview.cpp中的ftpview析构函数中加入下面的代码
# s% E1 G! P+ u& p% ICFtpView::~CFtpView()
% I" U7 m0 c. f{ 6 g- P7 d, L/ @0 R
if(m_pFtpConnection!=NULL)
* b* T; y$ ]1 U{ ' ^, v) b2 m7 k
m_pFtpConnection->Close(); + v" f7 f* c9 M8 l
delete m_pFtpConnection;   i3 A5 ?1 r: o  {+ z- W6 `
}
3 M/ u+ k; T: s2 Idelete m_pInetSession; - A: u8 ~0 p. ]0 m1 W
}
, T% D- g( /  s  g) Y7 ^编译并且执行程序,如果连接出现问题,将会在一个消息框中报告出错消息。
  S$ q; f5 ]+ M, /发送文件到FTP文件服务器

---- 创建一个发送文件到FTP文件服务器的程序 3 S! A: ^. I+ C. z& j' M: l9 p& `) V% T
建立单文档程序ftpfw, 在ftpfwview.h中加入包含 #include  
# _! p/ [9 a  k6 m& S9 ~% o9 Y" m在ftpfwview.h中添加如下的成员变量
) `$ g2 a% k: ]3 l; E) {8 Rpublic: 8 m7 ^* G; t( o* H
bool m_bConnectionAttempted;
& v& B8 u- Y7 u) c1 C: jint m_nFileStatus; * {9 ~9 a& /. k+ f
在ftpview.cpp中的ftpview构造函数中加入下面的代码
) s2 w% k2 D# HCFtpfwView::CFtpfwView()
; j, ?) m/ [0 z7 r6 M9 r$ O2 /{
# @( Z5 C5 A9 v" r1 w2 }" m8 am_bConnectionAttempted=false; - S+ t; J2 V/ H9 q
}
2 N, M( U) D1 d" ^( e; /, ~使用ClassWizard加入新的类CFtpThread,该类派生于CWinThread 在ftpthread.h中加入如下变量
1 e! M. a& c! K4 m' npublic:
2 W7 k# d4 c2 {+ Y( F: Jstatic UINT PutFile(LPVOID Status);
0 i* r1 @% _+ u* B' I: /" H添加新类成员函数代码

UINT CFtpThread:utFile(LPVOID Status)
5 /& z' G& }" V, u3 ?& x- _: w{
! /: l; y9 {& `( i1 R+ s7 X/ sint *pnFileStatus; 9 D2 P' n' l9 M
CInternetSession *pInetSession; / j1 H9 U: {; F$ a
CFtpConnection *pFtpConnection=NULL; 9 f; G$ D2 x' _1 Q5 M" h. t5 ^7 ]
pnFileStatus=(int *)Status;
) x) D, d# z0 d3 b: }*pnFileStatus=0; 6 P: R$ F4 |$ a, ~" E2 o
pInetSession=new
  S4 |. c4 T3 m: ~+ Y) V0 RCInternetSession(AfxGetAppName(),1,
: L  M8 T1 E5 [1 gPRE_CONFIG_INTERNET_ACCESS); ! n& J! y; _0 A2 G
try
: }8 ]8 T. u3 y: a2 y" C8 R9 F$ Q" T{ : m# l3 f8 q, u' a# N
pFtpConnection=pInetSession->
: [/ B( L# J+ r3 BGetFtpConnection("192.34.45.0"); ' i3 t- M3 C: O# p& Q% i: y3 i
}   ?4 J1 O9 m* Q4 X; R* Q
catch(CInternetException *pEx) , z0 d* ?0 v/ M, }% d0 _
{
, r( z4 o0 I5 n8 V4 j, }pEx->Delete(); 9 Q! f! q' i# F0 o, L- u& n1 [) t
pFtpConnection=NULL;
5 Q/ p# i# N3 ?+ t1 ~# @2 b*pnFileStatus=-1;
' P$ P; G& `( f1 Xgoto BallOut;
* V7 m! j- Q' M0 U4 P} ! U9 c5 C6 Z+ u! }$ z
*pnFileStatus =1;
' b8 N4 h" I. @1 [pFtpConnection->Remove("test.txt");
/ J  r8 c2 f2 Y1 n' Y  X# Xif(!pFtpConnection->utFile 8 u$ F; X; e4 r( m
("test.txt","test.txt"))
( ?9 J+ A: i& w# `& T*pnFileStatus=-2; + k! U5 ]* z# z3 G* [; Z. L; j" p; v" B) ^
else
, |' ^6 X1 k& D4 U7 n0 v*pnFileStatus=2; 3 F2 g# Q. o% q9 e* d# Z# i( H
BallOut: " z0 p1 ]* V9 m
if(pFtpConnection!=NULL)
- T  D' V- W2 ^! c8 a{ ( d4 [! d1 [  O  O* H
pFtpConnection->Close();
  _1 j" F: z) N. i3 Ldelete pFtpConnection; + K+ q. m# Y/ I! /
} 0 [2 X  B2 T3 I7 h7 E% [" @
delete pInetSession;
0 w) z8 y) /5 B, P/ Q4 MAfxEndThread(0); ' d: Q3 ?2 y7 C0 `" p; /! {4 @8 T
return false;
# `. Z: y+ }( i7 G}
  B. M/ @$ N* R9 Q$ ^# M% f编辑ftpfwview.cpp中的OnDraw()函数 4 `6 {. `  Y; _6 j
void CFtpfwView::OnDraw(CDC* pDC)
) y) C0 @1 [- H8 t$ X, i" {{
6 U- b: B- M- B3 [3 H3 z6 I& i2 FCFtpfwDoc* pDoc = GetDocument(); ! ?3 n- {; }1 W5 |+ F
ASSERT_VALID(pDoc); / b3 a$ h. v/ h
if(!m_bConnectAttempted) ! ^; M6 N7 S4 M4 ]9 _7 e% J
{ 7 I* A" U) F" @. B
m_bConnectAttempted=TRUE; / U; I4 ^' e! Z
AfxBeginThread((AFX_THREADPROC)
. m' D6 P, ~$ W" G) ?6 VCFtpThread:utFile,&m_nFileStatus);
% b; r7 _! ~& G  U! q}
( L, g2 q5 b4 I/ e( O& /  |& G} ( V, h3 V2 y/ ]2 p+ |6 V& B; L$ f
编译并且执行程序,在连接和传输的过程中,应用程序仍然可以作自己的工作,这是因为传输的过程发生在线程中。
/ g* A7 i" I4 y# Y/ P( /7 @$ f总结语
4 |: l- P* z  n7 E---- 通过以上的程序我们可以明白FTP的工作原理,我们可以编制自己的获得FTP服务器的文件以及获得FTP服务器的根目录,亲自体验一下我们的程序工作的怎末样

' s6 u& m; J0 }2 Q( u6 V