充满梦想的FTP探索之旅(二)WinInet和FTP

需要

object content
Header Wininet.h
Library Wininet.lib
DLL Wininet.dll

变量声明

BOOL            bSuccess ;
HINTERNET       hIntSession, hFtpSession, hFind ;
HANDLE hLocalFind ;
WIN32_FIND_DATA finddata ;

Open an internet session

hIntSession = InternetOpen (CTelProxyApp::szTitle,           INTERNET_OPEN_TYPE_DIRECT,
            NULL, NULL, 0) ;

if(hIntSession == NULL)
{
    DWORD dwError = GetLastError();
    ErrLog(<<"InternetOpen error "<<dwError);
    return;
}

Open an FTP session

 hFtpSession = InternetConnect(hIntSession, m_szFTPServer,
                INTERNET_DEFAULT_FTP_PORT,
                m_szUser, m_szPassword, INTERNET_SERVICE_FTP, 0, 0);

 if(hFtpSession == NULL)
 {
     DWORD dwError = GetLastError();
     ErrLog(<<"InternetConnect error "<<dwError);
     InternetCloseHandle (hIntSession) ;
     return;
 }

ftp远程路径设置

//根目录为"/"
bSuccess = FtpSetCurrentDirectory (hFtpSession, m_szDirectory) ;
if(!bSuccess)
{
    DWORD dwLastError = GetLastError();
    if (dwLastError == ERROR_INTERNET_EXTENDED_ERROR) {
        char szLastResponse[1024] = { 0 };
        DWORD lastErrorResponse = 0;
        DWORD bufSize = sizeof(szLastResponse);
        if (InternetGetLastResponseInfo(&lastErrorResponse, szLastResponse, &bufSize))
        {
            //如果错误类似于550 /0: No such file or directory.
            if(memcmp(szLastResponse,"550",3) == 0)
            {
                bSuccess = FtpCreateDirectory (hFtpSession, m_szDirectory) ;
                bSuccess = FtpSetCurrentDirectory (hFtpSession, m_szDirectory) ;
                if(!bSuccess)
                {
                    ErrLog(<<szLastResponse<<"Cannot set directory to "<<m_szDirectory);
                    InternetCloseHandle (hFtpSession) ;
                    InternetCloseHandle (hIntSession) ;
                    return;
                }

        }else{
            ErrLog(<<"Cannot set directory to "<<m_szDirectory);
            InternetCloseHandle (hFtpSession) ;
            InternetCloseHandle (hIntSession) ;
            return;
        }
    }
    else //if InternetGetLastResponseInfo() failed
    {
        ErrLog(<<"Cannot set directory to "<<m_szDirectory);
        InternetCloseHandle (hFtpSession) ;
        InternetCloseHandle (hIntSession) ;
        return;
    }
}

}

获得ftp远程路径

char szCurrentDirectory[MAX_PATH] = {0};
DWORD dwLen = MAX_PATH;
bSuccess = FtpGetCurrentDirectory(hFtpSession, szCurrentDirectory, &dwLen);
if(!bSuccess)
{
    DWORD dwLastError = GetLastError(); //set dwLastError to GetLastError()
    ErrLog(<<"Cannot set directory to "<<m_szDirectory);

InternetCloseHandle (hFtpSession) ;
InternetCloseHandle (hIntSession) ;
return;

}

本地路径遍历上传

hLocalFind = ::FindFirstFile(CApp::getRecordFileTemplate().c_str(),&finddata);
if(hLocalFind == INVALID_HANDLE_VALUE)
{
    InternetCloseHandle (hFtpSession) ;
    InternetCloseHandle (hIntSession) ;
    return;
}

do
{
    bSuccess = FtpPutFile(hFtpSession,(CApp::getRecordFileDirectory()+=finddata.cFileName).c_str(),
                    finddata.cFileName,FTP_TRANSFER_TYPE_BINARY, 0); 

if(!bSuccess)
{
    DWORD dwErr = GetLastError();
    ErrLog(<<"upload file to ftp server fail.error "<<dwErr);
    InternetCloseHandle (hFtpSession) ;
    InternetCloseHandle (hIntSession) ;

    return;
}
DebugLog(<<"upload "<<finddata.cFileName);
}while(FindNextFile(hLocalFind,&finddata));

远程路径遍历下载

 hFind = FtpFindFirstFile (hFtpSession, TEMPLATE,
                           &finddata, 0, 0) ;

 if (hFind == NULL)
 {
      InternetCloseHandle (hFtpSession) ;
      InternetCloseHandle (hIntSession) ;
      return;
 }

 do
 {
      FtpGetFile (hFtpSession,
                  finddata.cFileName, finddata.cFileName, TRUE,
                  FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY, 0) ;
 }
 while (InternetFindNextFile (hFind, &finddata)) ;

完成销毁对象

InternetCloseHandle (hFind) ;
InternetCloseHandle (hFtpSession) ;
InternetCloseHandle (hIntSession) ;

注意

You should call theGetLastError function immediately when a function’s return value indicates that such a call will return useful data.

源文档 https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx

否则遇到错误,调用GetLastError查看错误码返回0.我之前没注意这个问题,日志输出放在了GetlastError前面,结果ftp函数返回FALSE,查看GetLastError的错误码为0,颇是束手无策。

参考

? <<Windows程序设计>> WinInet和FTP
? <<Visual C++ 网络高级编程>> FTP协议的实现
? WinINet Functions
时间: 2024-10-16 19:52:46

充满梦想的FTP探索之旅(二)WinInet和FTP的相关文章

充满梦想的FTP探索之旅(一)FTP服务器Serv-u配置

ftp服务器 IIS Serv-u Serv-u配置 step 1 新建域 点击新建域,开始域的创建. 设定域名及域名说明.每个域名都是唯一的标志符,用于区分文件服务器上的其他域. 设定协议端口.默认即可.如果有端口占用,会有警告符号,换用其它端口即可.FTP端口请保持默认. 设定IP 设定密码加密模式. step 2 新建用户 使用"向导"创建用户 设定用户名 设定密码 设定本地路径 设定用户权限 三,FTP的访问 在浏览器地址栏输入FTP服务器的地址(eg.127.0.0.1)

【C++探索之旅】第一部分第十二课:指针一出,谁与争锋

内容简介 1.第一部分第十二课:指针一出,谁与争锋 2.第一部分第十三课预告:第一部分小测验 指针一出,谁与争锋 上一课<[C++探索之旅]第一部分第十一课:小练习,猜单词>中,我们用一个小游戏来总结了之前几课学习的知识点. 现在,终于来到第一部分的最后一个知识点了,也是C++的基础部分的最后一个讲题.之后进入第二部分,就会开始面向对象之旅.因此,这一课也注定不平凡.系好安全带吧,因为马力要加足了! 指针这个C系语言的难点(著名的C语言里也有指针),令无数英雄"尽折腰",也

【C++探索之旅】第二部分第一课:面向对象初探,string的惊天内幕

内容简介 1.第二部分第一课:面向对象初探,string的惊天内幕 2.第二部分第二课预告:掀起了"类"的盖头来(一) 面向对象初探,string的惊天内幕 上一课<[C++探索之旅]第一部分第十二课:指针一出,谁与争锋>中,大家辛苦了. 诚然,指针是不容易啃的硬骨头.不过,假以时日,小火慢炖,可以成为一碗上好的骨头汤,对你的C++水平那可是大补. 好了,口水擦一擦,我们正式进入C++探索之旅的第二部分啦,激动不?刚擦完的哈喇子可不要继续流啊. 这一部分的课程称为:C++之

【Web探索之旅】第一部分:什么是Web?

内容简介 1.Web探索之旅:开宗明义 2.第一部分第一课:什么是Web? 3.第一部分第二课:Web,服务和云 4.第一部分第三课:Web的诞生史 Web探索之旅:开宗明义 大家好. 我们这个系列课程相对比较简单,比[C语言探索之旅],[C++探索之旅],[Linux探索之旅],[TCP/IP网络探索之旅]简单,会让大家在轻松中理解关于Web的方方面面. 您是否对Web感兴趣但是不知道什么是Web呢? 您是否觉得"网络黑客"很神秘? 您是否不清楚Internet和Web有什么区别?

【C语言探索之旅】 第二部分第一课:模块化编程

内容简介 1.课程大纲 2.第二部分第一课: 模块化编程 3.第二部分第二课预告: 进击的指针,C语言王牌 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. C语言编程基础知识 什么是编程? 工欲善其事,必先利其器 你的第一个程序 变量的世界 运算那点事 条件表达式 循环语句 实战:第一个C语言小游戏 函数 练习题 习作:完善第一个C语言小游戏 C语言高级技术 模块化编程 进击的指针,C语言王牌 数组 字符串 预处理 创建你自己的变量

【C语言探索之旅】 第三部分第二课:SDL开发游戏之创建窗口和画布

内容简介 1.第三部分第二课: SDL开发游戏之创建窗口和画布 2.第三部分第三课预告: SDL开发游戏之显示图像 第三部分第二课:SDL开发游戏之创建窗口和画布 在上一课中,我们对SDL这个开源库做了介绍,也带大家配置了SDL的开发环境.请大家按照上一课的步骤创建一个SDL工程,能够初步运行. 如果遇到问题,可以百度,Google相关平台SDL的配置.或者联系小编. 当然了,有些朋友可能会说开发C语言游戏还可以用GTK+这个库,但是个人认为GTK+没有SDL那么适合开发游戏,其创建图形界面的能

【C语言探索之旅】 第二部分第二课:进击的指针,C语言的王牌!

内容简介 1.课程大纲 2.第二部分第二课: 进击的指针,C语言的王牌 3.第二部分第三课预告: 数组 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编写三个游戏. C语言编程基础知识 什么是编程? 工欲善其事,必先利其器 你的第一个程序 变量的世界 运算那点事 条件表达式 循环语句 实战:第一个C语言小游戏 函数 练习题 习作:完善第一个C语言小游戏 C语言高级技术 模块化编程 进击的指针,C语言王牌 数组 字符串 预处理 创建你自己的变量类型

【C++探索之旅】第一部分第十一课:小游戏,猜单词

内容简介 1.第一部分第十一课:小游戏,猜单词 2.第一部分第十二课预告:指针一出,谁与争锋 小练习 上一课<[C++探索之旅]第一部分第十课:文件读写,海阔凭鱼跃>中我们学习了读写文件的知识. 第一部分的课程也快接近尾声了,下一课我们会学习很重要的指针的知识.之后,我们就进入第二部分:面向对象编程了.哈哈哈,激动不? 目前为止,我们也学了不少内容:编译基本原理,IDE,变量,函数,条件语句,循环语句,引用,数组,文件读写,等等.你应该为自己感到自豪. 俗语说得好:实践是最好的老师.我们学了那

【C++探索之旅】第一部分第九课:数组威武,动静合一

内容简介 1.第一部分第九课:数组威武,动静合一 2.第一部分第十课预告:文件读写,海阔凭鱼跃 数组威武,动静合一 上一课<[C++探索之旅]第一部分第八课:传值引用,文件源头>中,我们学习了函数参数的不同传递形式:值传递和引用传递,也学习了如何用头文件和源文件来更好地组织项目. 在不少程序中,我们都需要使用多个相同类型的变量.例如:一个网站的用户名列表(一般是string类型):或者一场比赛的前10个最佳得分(一般是int类型). 类似地,C++和大多数编程语言一样,也有将多个相同类型的数据