从FTP的服务上下载txt文件,下载不了的问题(Download the txt file from the FTP service. The problem is that you can’t download it)

  近期有个项目,要从ftp上下载txt文件下来,因为txt文件有我这边项目所需要的报告,但是我在本机上运行却能从客户的ftp上能拉取下来(我的电脑为WIN10),但是到了线上的环境却下了。

开始的时候,我是觉得路径的问题,然后把取的路径更改为  strFtpDirTmp += _T(“\\*.txt”);   

也就是如下的代码,最后在本机(WIN10)上能拉到ftp服务器的txt文件,但是到了线上的环境却不行了。实现下载的代码如下(单独开了个线程来下载):

  static THREAD_RETURN __STDCALL ThreadGetRptFromFtp(void *arglist)   {     CZzxFxImpl* pThis = (CZzxFxImpl*)arglist;     if (NULL == pThis)     {       return (THREAD_RETURN)0;     }

    CAdapter::InterlockedIncrement(&pThis->m_getFtpRptThreadCnt);     pThis->m_getRptThreadExitFlag = false;     pThis->g_pInetSession = NULL; //会话对象     pThis->g_pFtpConnection = NULL; //连接对象     //新建对话     pThis->g_pInetSession = new CInternetSession(AfxGetAppName(), 1, PRE_CONFIG_INTERNET_ACCESS);     try     {       //新建连接对象       pThis->g_pFtpConnection = pThis->g_pInetSession->GetFtpConnection(pThis->m_FtpAddr.c_str(), pThis->m_FtpUid.c_str(), pThis->m_FtpPwd.c_str());     }     catch (CInternetException *pEx)     {       TCHAR szError[1024];       CString strError = “”;       if (pEx->GetErrorMessage(szError, 1024))       {         string strLogInfo = cstr::format(“连接FTP服务器失败,失败原因 %s”, szError);       CSmsTools::GetInstance().WriteLogMsg(strLogInfo.c_str(), strLogInfo.length(), CSmsTools::LOG_LEVEL_ERROR);       }       else       {         string strLogInfo = cstr::format(“连接FTP服务器失败,失败原因:未知异常”);         CSmsTools::GetInstance().WriteLogMsg(strLogInfo.c_str(), strLogInfo.length(), CSmsTools::LOG_LEVEL_ERROR);       }       pEx->Delete();       pThis->g_pFtpConnection = NULL;

      return 0;     }

    try     {       memset(pThis->m_szLocalPath, 0x0, sizeof(pThis->m_szLocalPath));       CAdapter::GetCurrentPath(pThis->m_szLocalPath, MAX_PATH);       strcat(pThis->m_szLocalPath, “LocalRptFile”);       if (!CAdapter::PathFileExists(pThis->m_szLocalPath))       {       CAdapter::CreateDirectory(pThis->m_szLocalPath, 0);       }       //创建会话成功       while (!pThis->m_getRptThreadExitFlag)       {         //设置远程服务端状态报告获取目录         BOOL bSetDir = pThis->g_pFtpConnection->SetCurrentDirectory(pThis->m_FtpRptDir.c_str());

        CFtpFileFind RemoteFinder(pThis->g_pFtpConnection); //远程查找文件对象         // pRemoteFinder = new CFtpFileFind(g_pFtpConnection);

        CString strFtpDirTmp = pThis->m_FtpRptDir.c_str();         //strFtpDirTmp += “*”;         strFtpDirTmp += _T(“\\*.txt”);

        BOOL bFindFile = RemoteFinder.FindFile(strFtpDirTmp); //获取目录下所有的文件         //BOOL bFindFile = RemoteFinder.FindFile(_T(“*”)); //获取目录下所有的文件         int nFileCnt = 0;         while (bFindFile)         {           bFindFile = RemoteFinder.FindNextFile();           nFileCnt++;           CString strFile = RemoteFinder.GetFileName();

          CString strLoaclFilePath = “”;           strLoaclFilePath.Format(“%s\\%s”, pThis->m_szLocalPath, strFile); //下载到本地文件夹的全路径

          CString strErrMsgTmp = “”;           BOOL bGetRlt = pThis->g_pFtpConnection->GetFile(strFile, strLoaclFilePath, FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY); //下载           if (bGetRlt) //下载成功           {             BOOL bRemove = pThis->g_pFtpConnection->Remove(strFile); //删除             if (!bRemove) //删除失败             {               string strLogInfo = cstr::format(“文件:%s 删除失败,失败代码:%d”, strFile, GetLastError());               CSmsTools::GetInstance().WriteLogMsg(strLogInfo.c_str(), strLogInfo.length(), CSmsTools::LOG_LEVEL_ERROR);               break;             }           }           else //下载失败           {             string strLogInfo = cstr::format(“文件:%s 下载失败,失败代码:%d”, strFile, GetLastError());             CSmsTools::GetInstance().WriteLogMsg(strLogInfo.c_str(), strLogInfo.length(), CSmsTools::LOG_LEVEL_ERROR);             continue;           }

          //解析本地文件夹中状态报告文件           pThis->ParseLocalDirectoryRptFile(strLoaclFilePath);

          Sleep(100);         }         RemoteFinder.Close();         Sleep(1000 * 5);       }     }     catch (…) //GetErrorMessage     {       string strLogInfo = cstr::format(“下载异常”);       CSmsTools::GetInstance().WriteLogMsg(strLogInfo.c_str(), strLogInfo.length(), CSmsTools::LOG_LEVEL_ERROR);     }

    CAdapter::InterlockedDecrement(&pThis->m_getFtpRptThreadCnt);     return 0;   }

  最后到了线上再执行,还是从客户的FTP服务器上拉取不了txt文件下来,那就是把  strFtpDirTmp += “*”;  改成  strFtpDirTmp += _T(“\\*.txt”);   是无效的了。

然后我想想了,这里没有几个函数 ,也都是成熟悉的东西(ftp这协议已经很久了)。最后把问题定在了线上环境的系统 上,因为线上的环境是Windows  server  2012,最后找了资料,把GetFtpConnection 的后面再加上2个参数,这样就能正常运行了,路径也换为了 strFtpDirTmp += “*”;     代码更改后如下:

  static THREAD_RETURN __STDCALL ThreadGetRptFromFtp(void *arglist)  {    CZzxFxImpl* pThis = (CZzxFxImpl*)arglist;    if (NULL == pThis)    {      return (THREAD_RETURN)0;    }

    CAdapter::InterlockedIncrement(&pThis->m_getFtpRptThreadCnt);    pThis->m_getRptThreadExitFlag = false;    pThis->g_pInetSession = NULL; //会话对象    pThis->g_pFtpConnection = NULL; //连接对象    //新建对话    pThis->g_pInetSession = new CInternetSession(AfxGetAppName(), 1, PRE_CONFIG_INTERNET_ACCESS);    try    {      //新建连接对象      pThis->g_pFtpConnection = pThis->g_pInetSession->GetFtpConnection(pThis->m_FtpAddr.c_str(), pThis->m_FtpUid.c_str(), pThis->m_FtpPwd.c_str(),21,TRUE);    }    catch (CInternetException *pEx)    {      TCHAR szError[1024];      CString strError = “”;      if (pEx->GetErrorMessage(szError, 1024))      {        string strLogInfo = cstr::format(“连接FTP服务器失败,失败原因 %s”, szError);      CSmsTools::GetInstance().WriteLogMsg(strLogInfo.c_str(), strLogInfo.length(), CSmsTools::LOG_LEVEL_ERROR);      }      else      {        string strLogInfo = cstr::format(“连接FTP服务器失败,失败原因:未知异常”);        CSmsTools::GetInstance().WriteLogMsg(strLogInfo.c_str(), strLogInfo.length(), CSmsTools::LOG_LEVEL_ERROR);      }      pEx->Delete();      pThis->g_pFtpConnection = NULL;

      return 0;    }

    try    {      memset(pThis->m_szLocalPath, 0x0, sizeof(pThis->m_szLocalPath));      CAdapter::GetCurrentPath(pThis->m_szLocalPath, MAX_PATH);      strcat(pThis->m_szLocalPath, “LocalRptFile”);      if (!CAdapter::PathFileExists(pThis->m_szLocalPath))      {      CAdapter::CreateDirectory(pThis->m_szLocalPath, 0);      }      //创建会话成功      while (!pThis->m_getRptThreadExitFlag)      {        //设置远程服务端状态报告获取目录        BOOL bSetDir = pThis->g_pFtpConnection->SetCurrentDirectory(pThis->m_FtpRptDir.c_str());

        CFtpFileFind RemoteFinder(pThis->g_pFtpConnection); //远程查找文件对象        // pRemoteFinder = new CFtpFileFind(g_pFtpConnection);

        CString strFtpDirTmp = pThis->m_FtpRptDir.c_str();        strFtpDirTmp += “*”;

        BOOL bFindFile = RemoteFinder.FindFile(strFtpDirTmp); //获取目录下所有的文件        //BOOL bFindFile = RemoteFinder.FindFile(_T(“*”)); //获取目录下所有的文件        int nFileCnt = 0;        while (bFindFile)        {          bFindFile = RemoteFinder.FindNextFile();          nFileCnt++;          CString strFile = RemoteFinder.GetFileName();

          CString strLoaclFilePath = “”;          strLoaclFilePath.Format(“%s\\%s”, pThis->m_szLocalPath, strFile); //下载到本地文件夹的全路径

          CString strErrMsgTmp = “”;          BOOL bGetRlt = pThis->g_pFtpConnection->GetFile(strFile, strLoaclFilePath, FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY); //下载          if (bGetRlt) //下载成功          {            BOOL bRemove = pThis->g_pFtpConnection->Remove(strFile); //删除            if (!bRemove) //删除失败            {              string strLogInfo = cstr::format(“文件:%s 删除失败,失败代码:%d”, strFile, GetLastError());              CSmsTools::GetInstance().WriteLogMsg(strLogInfo.c_str(), strLogInfo.length(), CSmsTools::LOG_LEVEL_ERROR);              break;            }          }          else //下载失败          {            string strLogInfo = cstr::format(“文件:%s 下载失败,失败代码:%d”, strFile, GetLastError());            CSmsTools::GetInstance().WriteLogMsg(strLogInfo.c_str(), strLogInfo.length(), CSmsTools::LOG_LEVEL_ERROR);            continue;          }

          //解析本地文件夹中状态报告文件          pThis->ParseLocalDirectoryRptFile(strLoaclFilePath);

          Sleep(100);        }        RemoteFinder.Close();        Sleep(1000 * 5);      }    }    catch (…) //GetErrorMessage    {      string strLogInfo = cstr::format(“下载异常”);      CSmsTools::GetInstance().WriteLogMsg(strLogInfo.c_str(), strLogInfo.length(), CSmsTools::LOG_LEVEL_ERROR);    }

    CAdapter::InterlockedDecrement(&pThis->m_getFtpRptThreadCnt);    return 0;  }

  也就是这句后面的2个参数起了重要作用

  pThis->g_pFtpConnection = pThis->g_pInetSession->GetFtpConnection(pThis->m_FtpAddr.c_str(), pThis->m_FtpUid.c_str(), pThis->m_FtpPwd.c_str(),21,TRUE);

  具体的可看下FTP的被动连接和主动连接。

  接着再把程序拿到线上跑,就能从客户的FTP服务器上拉取txt文件的了。

  注:最后一个问题,就是本机上我从ftp下载很快,但是到了线上生产环境很慢的话,那就是线上的网线的问题的了,这时候就要和客户的ftp所在的IP(也就是接入的运营商,移动,电信搞清楚)。因为线上的环境数据 出去有几个运营商(移动,联通,电信),要能从客户这里快速下载文件的话,就必须把这跑的程序所在的线上机子出去的IP单独为运营商移动的(因为客户的IP对应也是移动这块的)。。。

————————

Recently, there was a project to download the txt file from FTP, because the txt file has the report required by my project, but I can pull it down from the client’s FTP when I run on this computer (my computer is win10), but it goes down in the online environment.

At first, I thought the path was wrong, and then changed the path to strftpdirtmp + =_ T(“\\*.txt”);

That is, the following code can finally pull the txt file of the FTP server on the local machine (win10), but it can’t work in the online environment. The code for downloading is as follows (a separate thread is opened to download):

  static THREAD_RETURN __STDCALL ThreadGetRptFromFtp(void *arglist)   {     CZzxFxImpl* pThis = (CZzxFxImpl*)arglist;     if (NULL == pThis)     {       return (THREAD_RETURN)0;     }

CAdapter::InterlockedIncrement(&pThis->m_getFtpRptThreadCnt);     pThis-> m_ getRptThreadExitFlag = false;     pThis-> g_ pInetSession = NULL; // Session object     pThis-> g_ pFtpConnection = NULL; // Connection object / / create a new conversation     pThis-> g_ pInetSession = new CInternetSession(AfxGetAppName(), 1, PRE_ CONFIG_ INTERNET_ ACCESS);     try     { / / create a new connection object       pThis-> g_ pFtpConnection = pThis-> g_ pInetSession-> GetFtpConnection(pThis->m_FtpAddr.c_str(), pThis-> m_ FtpUid. c_ str(), pThis-> m_ FtpPwd. c_ str());     }     catch (CInternetException *pEx)     {       TCHAR szError[1024];       CString strError = “”;       if (pEx->GetErrorMessage(szError, 1024))       { String strloginfo = CSTR:: format (“failed to connect to FTP server, failure reason% s”, szerror);       CSmsTools::GetInstance(). WriteLogMsg(strLogInfo.c_str(), strLogInfo. length(), CSmsTools::LOG_ LEVEL_ ERROR);       }       else       { String strloginfo = CSTR:: format (“failed to connect to FTP server, failure reason: unknown exception”);         CSmsTools::GetInstance(). WriteLogMsg(strLogInfo.c_str(), strLogInfo. length(), CSmsTools::LOG_ LEVEL_ ERROR);       }       pEx-> Delete();       pThis-> g_ pFtpConnection = NULL;

return 0;     }

try     {       memset(pThis->m_szLocalPath, 0x0, sizeof(pThis->m_szLocalPath));       CAdapter::GetCurrentPath(pThis->m_szLocalPath, MAX_PATH);       strcat(pThis->m_szLocalPath, “LocalRptFile”);       if (!CAdapter::PathFileExists(pThis->m_szLocalPath))       {       CAdapter::CreateDirectory(pThis->m_szLocalPath, 0);       } / / create session succeeded       while (!pThis->m_getRptThreadExitFlag)       { / / set the remote server status report acquisition directory         BOOL bSetDir = pThis-> g_ pFtpConnection-> SetCurrentDirectory(pThis->m_FtpRptDir.c_str());

        CFtpFileFind RemoteFinder(pThis->g_pFtpConnection); //远程查找文件对象         // pRemoteFinder = new CFtpFileFind(g_pFtpConnection);

CString strFtpDirTmp = pThis-> m_ FtpRptDir. c_ str();         //strFtpDirTmp += “*”;         strFtpDirTmp += _ T(“\\*.txt”);

BOOL bFindFile = RemoteFinder. FindFile(strFtpDirTmp); // Get all files in the directory         //BOOL bFindFile = RemoteFinder. FindFile(_T(“*”)); // Get all files in the directory         int nFileCnt = 0;         while (bFindFile)         {           bFindFile = RemoteFinder. FindNextFile();           nFileCnt++;           CString strFile = RemoteFinder. GetFileName();

CString strLoaclFilePath = “”;           strLoaclFilePath. Format(“%s\\%s”, pThis->m_szLocalPath, strFile); // Full path to download to local folder

CString strErrMsgTmp = “”;           BOOL bGetRlt = pThis-> g_ pFtpConnection-> GetFile(strFile, strLoaclFilePath, FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY); // download If (bgetrlt) / / download succeeded           {             BOOL bRemove = pThis-> g_ pFtpConnection-> Remove(strFile); // delete If (! Bremove) / / deletion failed             { String strloginfo = CSTR:: format (“file:% s deletion failed, failure code:% d”, strFile, getlasterror());               CSmsTools::GetInstance(). WriteLogMsg(strLogInfo.c_str(), strLogInfo. length(), CSmsTools::LOG_ LEVEL_ ERROR);               break;             }           } Else / / download failed           { String strloginfo = CSTR:: format (“file:% s download failed, failure code:% d”, strFile, getlasterror());             CSmsTools::GetInstance(). WriteLogMsg(strLogInfo.c_str(), strLogInfo. length(), CSmsTools::LOG_ LEVEL_ ERROR);             continue;           }

/ / parse the status report file in the local folder           pThis-> ParseLocalDirectoryRptFile(strLoaclFilePath);

Sleep(100);         }         RemoteFinder. Close();         Sleep(1000 * 5);       }     }     catch (…) // GetErrorMessage     { String strloginfo = CSTR:: format (“download exception”);       CSmsTools::GetInstance(). WriteLogMsg(strLogInfo.c_str(), strLogInfo. length(), CSmsTools::LOG_ LEVEL_ ERROR);     }

    CAdapter::InterlockedDecrement(&pThis->m_getFtpRptThreadCnt);     return 0;   }

Finally, when you go online, you still can’t pull the txt file from the customer’s FTP server, that is, put “strftpdirtmp + =” * “; Change to strftpdirtmp + =_ T(“\\*.txt”); Is invalid.

Then I thought about it. There are few functions here, and they are all familiar things (FTP protocol has been used for a long time). Finally, the problem is determined on the system of the online environment, because the online environment is windows “server” 2012. Finally, I found the information and added two parameters after getftpconnection, so that it can run normally, and the path is changed to “strftpdirtmp + =” * “; The code is changed as follows:

  static THREAD_RETURN __STDCALL ThreadGetRptFromFtp(void *arglist)  {    CZzxFxImpl* pThis = (CZzxFxImpl*)arglist;    if (NULL == pThis)    {      return (THREAD_RETURN)0;    }

CAdapter::InterlockedIncrement(&pThis->m_getFtpRptThreadCnt);     pThis-> m_ getRptThreadExitFlag = false;     pThis-> g_ pInetSession = NULL; // Session object PThis – & gt; g_ pFtpConnection = NULL; // Connection object / / create a new conversation PThis – & gt; g_ pInetSession = new CInternetSession(AfxGetAppName(), 1, PRE_ CONFIG_ INTERNET_ ACCESS); Try {/ / create a new connection object PThis – & gt; g_pftpconnection = PThis – & gt; g_pinetsession – & gt; getftpconnection (PThis – & gt; m_ftpaddr. C_str(), PThis – & gt; m_ftpuid. C_str(), PThis – & gt; m_ftppwd. C_str(), 21, true);} catch (cinternetexception * PEX) {TCHAR szerror [1024]; CString strError = “”; if (PEX – & gt; geterrormessage (szerror, 1024)) {string strloginfo = CSTR:: format (“failed to connect to FTP server, failure reason% s”, szerror); csmstools:: getinstance(). Writelogmsg (strloginfo. C_str()) , strLogInfo. length(), CSmsTools::LOG_ LEVEL_ ERROR); } else {string strloginfo = CSTR:: format (“failed to connect to FTP server, failure reason: unknown exception”); csmstools:: getinstance(). Writelogmsg (strloginfo. C_str(), strloginfo. Length(), csmstools:: log_level_error);} PEX – & gt; Delete();       pThis-> g_ pFtpConnection = NULL;

return 0;     }

try    {      memset(pThis->m_szLocalPath, 0x0, sizeof(pThis->m_szLocalPath));      CAdapter::GetCurrentPath(pThis->m_szLocalPath, MAX_PATH);      strcat(pThis->m_szLocalPath, “LocalRptFile”);      if (!CAdapter::PathFileExists(pThis->m_szLocalPath) ){adapter:: createdirectory (PThis – & gt; m_szlocalpath, 0);} / / creating session succeeds while (! PThis – & gt; m_getrptthreadexitflag) {/ / set the remote server status report to get the directory bool bsetdir = PThis – & gt; g_pftpconnection – & gt; SetCurrentDirectory (PThis – & gt; m_ftprptdir. C_str());

        CFtpFileFind RemoteFinder(pThis->g_pFtpConnection); //远程查找文件对象        // pRemoteFinder = new CFtpFileFind(g_pFtpConnection);

CString strFtpDirTmp = pThis-> m_ FtpRptDir. c_ str();         strFtpDirTmp += “*”;

BOOL bFindFile = RemoteFinder. FindFile(strFtpDirTmp); // Get all files in the directory / / bool bfindfile = remotefinder FindFile(_T(“*”)); // Get all files in the directory int nfilecnt = 0;         while (bFindFile)        {          bFindFile = RemoteFinder.FindNextFile();          nFileCnt++;          CString strFile = RemoteFinder.GetFileName();

CString strLoaclFilePath = “”;           strLoaclFilePath. Format(“%s\\%s”, pThis->m_szLocalPath, strFile); // Full path to download to local folder

CString strErrMsgTmp = “”;           BOOL bGetRlt = pThis-> g_ pFtpConnection-> GetFile(strFile, strLoaclFilePath, FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY); // Download if (bgetrlt) / / download succeeds {bool bremove = PThis – & gt; g_pftpconnection – & gt; remove (strFile); / / delete if (! Bremove) / / delete fails {string strloginfo = CSTR:: format (“file:% s deletion failed, failure code:% d”, strFile, getlasterror()); csmstools:: getinstance(). Writelogmsg (strloginfo. C_str(), strloginfo. Length()) , CSmsTools::LOG_ LEVEL_ ERROR);               break; }} else / / download failed {string strloginfo = CSTR:: format (“file:% s download failed, failure code:% d”, strFile, getlasterror()); csmstools:: getinstance()) .WriteLogMsg(strLogInfo.c_str(), strLogInfo. length(), CSmsTools::LOG_ LEVEL_ ERROR);             continue;           }

/ / parse the status report file PThis – & gt; ParseLocalDirectoryRptFile(strLoaclFilePath);

Sleep(100);         }        RemoteFinder. Close();         Sleep(1000 * 5);       }    }    catch (…) // Geterrormessage {string strloginfo = CSTR:: format (“download exception”); csmstools:: getinstance(). Writelogmsg (strloginfo. C_str(), strloginfo. Length(), csmstools:: log_level_error);}

    CAdapter::InterlockedDecrement(&pThis->m_getFtpRptThreadCnt);    return 0;  }

That is, the two parameters behind this sentence play an important role

  pThis->g_pFtpConnection = pThis->g_pInetSession->GetFtpConnection(pThis->m_FtpAddr.c_str(), pThis->m_FtpUid.c_str(), pThis->m_FtpPwd.c_str(),21,TRUE);

See the passive connection and active connection of FTP for details.

Then take the program to the online run, and you can pull the txt file from the customer’s FTP server.

Note: the last problem is that I download FTP very quickly on this machine, but if the online production environment is very slow, it is the problem of the online network cable. At this time, it is necessary to find out with the IP of the customer’s FTP (that is, the access operator, mobile and Telecom). Because there are several operators (China Mobile, China Unicom and China Telecom) for online environmental data, if you want to quickly download files from customers, you must move the IP of the online machine where the running program is located separately for the operators (because the customer’s IP is also moved)…