ftp文件上传下载模块概述
1.1 开发背景
如果用户不使用FTP客户端软件,而是直接登录到FTP服务器来上传或下载FTP文件,会存在许多不足。例如,在同时下载多个文件时,如何暂停或继续某个文件的下载,如果下载大量文件,如何在任务下载完成后关闭计算机。这就是FTP客户端软件的作用,也是笔者设计本章程序的主要原因。
1.2 需求分析
FTP文件上传下载模块的主要功能是实现FTP文件的多任务上传、下载,对于实现FTP 文件的上传和下载,可以使用MFC提供的WinInet相关类非常方便地实现,模块的难点在于多任务,需要为每个上传或下载的任务维护一个单独的线程,用户可以暂停和取消任务。在关键技术部分笔者将介绍如何实现FTP文件多任务下载。
1.3 模块预览
FTP文件上传下载模块只包含一个主对话框,但是主对话框却由登录信息栏、工具栏、本地信息窗口、远程FTP服务器信息窗口和任务列表共5个子窗口构成。下面分别给出各个窗口的效果图。
FTP文件上传下载模块主窗口效果图如图1所示。
图1 FTP文件上传下载模块主窗口
登录信息栏效果如图2所示工具栏窗口效果如图3所示。
图3 工具栏窗口
本地信息窗口效果图如图4所示。
图4 本地信息窗口
远程FTP服务器信息窗口效果如图5所示。
任务列表窗口运行效果如图6所示。
图6 任务列表窗口
关键技术
1.1 设计类似于资源管理器的列表视图控件
在设计FTP文件上传下载模块时,首先需要确定采用何种方式显示本地和FTP服务器上的目录和文件。为了模仿Windows资源管理器的效果,笔者采用了列表视图控件——CListCtrl来实现目录和文件的显示。但是,MFC提供的默认的CListCtrl无法实现Windows 资源管理器的效果,我们必须重新设计一个列表视图控件。该控件需要具备的功能有以本地系统默认的图标显示目录和文件的图标,在控件中双击某一个目录将进入子目录,按“Back Space”键将返回上一级目录,实现对某一列的升序、降序排列,并以箭头标识。控件的设计效果如图13.4所示。在设计控件之前,读者需要对CListCtrl控件有所了解。CListCtrl 控件主要有两部分构成,第一部分是列头部分,由CHeaderCtrl控件构成,第二部分是表格部分。当在列头部分绘制排序箭头时,实际上是在CHeaderCtrl控件上进行的。
下面介绍控件的详细设计过程。首先设计列头控件,因为需要绘制排序列的标记。
(1)从CHeaderCtrl类派生一个子类——CSortHeaderCtrl,向该类中添加成员变量。
(1)从CHeaderCtrl类派生一个子类——CSortHeaderCtrl,向该类中添加成员变量。
int m_nSortColumn; //排序列
BOOL m_bAscend; //是否为升序
(2)在构造函数中初始化成员变量。
CSortHeaderCtrl::CSortHeaderCtrl()
{
m_nSortColumn = -1;
m_bAscend = TRUE;
}
(3)向CSortHeaderCtrl类中添加SetSortColomn方法,用于设置排序列和排序列的自绘风格。
void CSortHeaderCtrl::SetSortColomn(int nColumn, BOOL bAscend)
{
m_nSortColumn = nColumn; //设置排序列
m_bAscend = bAscend; //设置排序方式
HD_ITEM hItem;
hItem.mask = HDI_FORMAT;
GetItem( nColumn, &hItem ) ; //获取列信息
hItem.fmt |= HDF_OWNERDRAW; //设置列自绘风格
SetItem( nColumn, &hItem ); //设置列信息
Invalidate(); //更新控件
}
(4)改写CSortHeaderCtrl类的DrawItem方法,根据排序方式绘制排序列的箭头符号。
void CSortHeaderCtrl::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
CDC dc; //定义设备上下文
dc.Attach( lpDrawItemStruct->hDC ); //附加设备上下文句柄
const int nSavedIndex = dc.SaveDC(); //保存设备上下文
CRect rc( lpDrawItemStruct->rcItem ); //获取当前列区域
CBrush brush( GetSysColor( COLOR_3DFACE ) ); //定义背景画刷dc.FillRect( rc, &brush ); //填充画刷
TCHAR szText[ 256 ]; //定义字符数组,存储列文本
HD_ITEM hditem;
hditem.mask = HDI_TEXT | HDI_FORMAT;
hditem.pszText = szText;
https://www.doczj.com/doc/8312333506.html,hTextMax = 255;
GetItem( lpDrawItemStruct->itemID, &hditem ); //获取当前的项目信息
UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP |
DT_VCENTER | DT_END_ELLIPSIS ; //设置绘制的文本格式if( hditem.fmt & HDF_CENTER)
uFormat |= DT_CENTER;
else if( hditem.fmt & HDF_RIGHT)
uFormat |= DT_RIGHT;
else
uFormat |= DT_LEFT;
if( lpDrawItemStruct->itemState == ODS_SELECTED )//列是否被选中{
rc.left++; //调整列的区域
rc.top += 2;
rc.right++;
}
CRect rcIcon( lpDrawItemStruct->rcItem ); //定义箭头显示区域
const int iOffset = ( rcIcon.bottom - rcIcon.top ) / 4;
if( lpDrawItemStruct->itemID == (UINT) m_nSortColumn )
rc.right -= 3 * iOffset;
rc.left += iOffset;
rc.right -= iOffset;
if( rc.left < rc.right )
dc.DrawText( szText, -1, rc, uFormat ); //绘制列文本
//绘制箭头
if( lpDrawItemStruct->itemID == (UINT) m_nSortColumn )
{
CPen penLight( PS_SOLID, 1, GetSysColor( COLOR_3DHILIGHT ) ); //定义
浅颜色画笔
CPen penShadow( PS_SOLID, 1, GetSysColor( COLOR_3DSHADOW ) );//定义
深颜色画笔
CPen* pOldPen = dc.SelectObject( &penLight ); //选中画笔
if( m_bAscend ) //绘制向上的箭头
{
dc.MoveTo( rcIcon.right - 2 * iOffset, iOffset);
dc.LineTo( rcIcon.right - iOffset, rcIcon.bottom - iOffset - 1 );
dc.LineTo( rcIcon.right - 3 * iOffset - 2, rcIcon.bottom - iOffset - 1 );
dc.SelectObject( &penShadow );
dc.MoveTo( rcIcon.right - 3 * iOffset - 1, rcIcon.bottom - iOffset - 1 );
dc.LineTo( rcIcon.right - 2 * iOffset, iOffset - 1);
}
else //绘制向下的箭头
{
dc.MoveTo( rcIcon.right - iOffset - 1, iOffset );
dc.LineTo( rcIcon.right - 2 * iOffset - 1, rcIcon.bottom - iOffset );
dc.SelectObject( &penShadow );
dc.MoveTo( rcIcon.right - 2 * iOffset - 2, rcIcon.bottom - iOffset );
dc.LineTo( rcIcon.right - 3 * iOffset - 1, iOffset );
dc.LineTo( rcIcon.right - iOffset - 1, iOffset );
}
dc.SelectObject( pOldPen ); //恢复原来选择的画笔}
dc.RestoreDC( nSavedIndex ); //恢复之前的设备上下文
dc.Detach(); //从设备上下文中分离设备上下文句柄}
在设计完列头控件之后,下面开始设计列表视图控件。
(1)从CListCtrl类派生一个子类——CSortListCtrl,向该类中添加如下成员变量。
CString m_BaseDir; //基目录
CString m_CurDir; //记录当前列表中文件的目录
int m_nListType; //列表类型,0表示显示本地信息,1,表示显示FTP服务器信息,默认为0
CInternetSession m_Session; //Internet会话
CString m_FtpServer,m_Port,m_User,m_Password; //FTP服务器,端口号,用户名和密码
CSortHeaderCtrl m_ctlHeader; //列头
int m_nNumColumns; //列数
int m_nSortColumn; //排序列
BOOL m_bAscend; //是否升序排列
(2)定义一个类CItemData,描述项目的额外数据,主要用于记录某一行各个列的文本。当排序时,需要根据排序函数的参数获取排序列的文本以便进行比较。
class CItemData
{
public:
CItemData() //构造函数
{
m_ColumnTexts = NULL;
m_dwData = 0;
}
LPTSTR* m_ColumnTexts; //记录当前行所有列文本
DWORD m_dwData; //视图项数据
private:
//禁止复制
CItemData( const CItemData& );
CItemData& operator=( const CItemData& );
};
(3)向CSortListCtrl 类中添加SetItemDataList方法,为项目关联一个自定义的数据结构——CItemData。在进行排序时需要根据该数据结构获取排序列的文本。
BOOL CSortListCtrl::SetItemDataList( int iItem, LPTSTR* pchTexts )
{
if (CListCtrl::GetItemData( iItem ) == NULL ) //判断关联的数据是否为空
{
CItemData* pItemData = new CItemData(); //构建一个CItemData对象
pItemData->m_ColumnTexts = pchTexts; //设置列文本
//设置项目数据
return CListCtrl::SetItemData( iItem, (DWORD)pItemData);
}
}
(4)向CSortListCtrl 类中添加GetItemDataList方法,获取项目关联的数据。
LPTSTR* CSortListCtrl::GetItemDataList( int iItem ) const
{
ASSERT( iItem < GetItemCount() );
CItemData* pItemData = ( CItemData* )CListCtrl::GetItemData( iItem ) ; //获取关联数据
return pItemData->m_ColumnTexts; //返回列文本
}
(5)向CSortListCtrl 类中添加SetItemText方法,设置项目的文本,同时修改关联的CItemData结构的列文本。
BOOL CSortListCtrl::SetItemText( int nItem, int nSubItem, LPCTSTR lpszText )
{
if( !CListCtrl::SetItemText( nItem, nSubItem, lpszText ) ) //调用基类的方法设置文本
return FALSE;
LPTSTR* pszTexts = GetItemDataList( nItem ); //获取行各列文本
LPTSTR pszText = pszTexts[ nSubItem ]; //获取当前列文本
delete[] pszText; //释放文本数据
pszText = new TCHAR[ lstrlen( lpszText ) + 1 ];
lstrcpy( pszText, lpszText ); //重新设置文本
pszTexts[ nSubItem ] = pszText;
return TRUE;
}
(6)向CSortListCtrl 类中添加AddItem方法,用于添加新行,设置行各列文本。
int CSortListCtrl::AddItem( LPCTSTR pszText, ... )
{
int nIndex = InsertItem( GetItemCount(), pszText ); //添加行,返回行索引
LPTSTR* pszColumnTexts = new LPTSTR[ m_nNumColumns ]; //记录各列文本
pszColumnTexts[ 0 ] = new TCHAR[ lstrlen( pszText ) + 1 ];
lstrcpy( pszColumnTexts[ 0 ], pszText ); //设置第一列文本
va_list list;
va_start( list, pszText );
for( int nColumn = 1; nColumn < m_nNumColumns; nColumn++ ) //设置其他列文本
{
pszText = va_arg( list, LPCTSTR );
CListCtrl::SetItem( nIndex, nColumn, LVIF_TEXT, pszText, 0, 0, 0, 0 );
pszColumnTexts[ nColumn ] = new TCHAR[ lstrlen( pszText ) + 1 ];
lstrcpy( pszColumnTexts[ nColumn ], pszText );
}
va_end( list );
SetItemDataList( nIndex, pszColumnTexts ); //设置行关联数据
return nIndex;
}
(7)向CSortListCtrl 类中添加SetColumns方法,向列表视图控件中添加列,设置列文本。该方法的主要作用是可以一次添加多列,并且可以指定列的宽度。
//设置列,格式为文本,宽度; 文本,宽度; ......
BOOL CSortListCtrl::SetColumns( const CString& strHeadings )
{
int nStart = 0;
for( ;; )
{
int nComma = strHeadings.Find( _T(','), nStart ); //查找“,”标记
if( nComma == -1 )
break;
CString strHeading = strHeadings.Mid( nStart, nComma - nStart ); //获取文本
nStart = nComma + 1; //掠过“,”
int nSemiColon = strHeadings.Find( _T(';'), nStart ); //查找“;”
if( nSemiColon == -1 ) //查找到了结尾
nSemiColon = strHeadings.GetLength();
int nWidth = atoi( strHeadings.Mid( nStart, nSemiColon - nStart ) ); //获取宽度
nStart = nSemiColon + 1; //指向下一列信息
if( InsertColumn( m_nNumColumns++, strHeading, LVCFMT_LEFT, nWidth ) == -1 )
return FALSE; //插入列
}
return TRUE;
}
(8)向CSortListCtrl 类中添加GetIconFromExtendedName方法,根据文件的类型获取系统对应的文件图标。GetIconFromExtendedName方法首先判断参数是文件还是目录,如果是文件,则调用SHGetFileInfo函数并传递SHGFI_USEFILEATTRIBUTES标记来依据文件类型返回图标,如果为目录,则以当前目录为参数,调用SHGetFileInfo函数获取系统目录的图标。
//根据文件类型获取图标
HICON CSortListCtrl::GetIconFromExtendedName(LPCTSTR lpName)
{
SHFILEINFO shInfo; //定义外壳文件信息
int nIcon = 0;
CString extension = lpName;
CString csName = "text"+extension; //设置一个临时的文件名
int nPos = csName.ReverseFind('.'); //判断是否为文件
if (nPos >0)
{
//获取文件图标
SHGetFileInfo(csName ,FILE_ATTRIBUTE_NORMAL,&shInfo,sizeof(shInfo),
SHGFI_ICON | SHGFI_SMALLICON|SHGFI_USEFILEATTRIBUTES );
}
else //参数表示一个目录
{
char chPath[MAX_PATH] = {0};
GetCurrentDirectory(MAX_PATH,chPath); //获取当前目录
SHGetFileInfo(chPath,FILE_ATTRIBUTE_NORMAL,&shInfo,sizeof(shInfo), SHGFI_ICON | SHGFI_SMALLICON ); //获取目录图标}
nPos = shInfo.iIcon;
return shInfo.hIcon; //返回获取的图标}
(9)向CSortListCtrl 类中添加DisplayPath方法,列举本地或FTP服务器目录和文件信
息。该方法的作用非常重要,在程序的多处地方都需要调用DisplayPath方法,例如,在视图列表中显示本地系统中的某一个目录下的子目录和文件,用户按“Back Space”键返回上一级目录等,这些都需要调用DisplayPath方法来实现。
DisplayPath方法代码较多,但是并不复杂。首先根据成员变量m_nListType来判断显示的是本地系统目录还是FTP服务器上的目录。以显示本地系统目录为例,使用CFileFind 类来遍历当前目录的直接子目录和文件,如果是文件,则读取文件的修改日期和大小信息,如果是目录,则标记为文件夹,将这些信息添加到列表视图中,然后获取文件关联的图标索引,设置视图项显示的图像索引,最后为了区分列表视图中的项目表示的是文件还是目录,为每个视图项设置一个额外的整数值,0表示文件,1表示目录。
void CSortListCtrl::DisplayPath(LPCTSTR lpPath,CFtpConnection* pTemp)
{
DeleteAllItems(); //删除所有视图项
if (m_nListType==0) //显示本地系统信息
{
BOOL bFind; //记录查找结果
CFileFind flFind; //定义文件查找对象
CString csPath = lpPath; //记录参数信息
m_CurDir = lpPath; //设置当前目录,进入子目录或返回上一级目录时需要依据当前目录
if ( csPath.Right(1) != "\\" ) //保证目录以\结尾
{
csPath += "\\";
m_CurDir +="\\";
}
csPath += "*.*"; //在目录结尾添加*.*用于查找文件
bFind = flFind.FindFile(csPath); //开始查找文件
CString csText,csFileSize,csDataTime;
while ( bFind ) //设置列表当前显示的目录
{
bFind = flFind.FindNextFile(); //查找下一个文件
if ( !flFind.IsDots() && !flFind.IsHidden())
{
__int64 lFileLen = flFind.GetLength64();//获取文件长度
if (flFind.IsDirectory()) //判断是否为目录
{
csFileSize = "文件夹";
}
else //如果是文件
{
//获取文件的大小
double fGB = lFileLen /(double)(1024*1024*1024);
if (fGB < 1) //判断文件是否小于1G
{
double fMB = lFileLen / (double)(1024*1024);
if (fMB < 1) //判断文件是否小于1MB
{
double fBK = lFileLen / (double)(1024);
if (fBK >1) //判断文件是否小于1KB
{
csFileSize.Format("%2.2f KB",fBK);
}
else //使用位作为单位
{
csFileSize.Format("%i B",lFileLen);
}
}
else
{
csFileSize.Format("%2.2f MB",fMB);
}
}
else
{
csFileSize.Format("%2.2f GB",fGB);
}
}
csText = flFind.GetFileName(); //获取文件名称
CTime time;
flFind.GetCreationTime(time); //获取文件日期
csDataTime = time.Format("%Y-%m-%d %H:%M"); //格式化日期
int nItem = AddItem(csText,csFileSize,csDataTime); //添加视图项
//设置文件显示的图标
SHFILEINFO shInfo;
int nIcon = 0;
SHGetFileInfo(flFind.GetFilePath(),0,&shInfo,sizeof(shInfo),SHGFI_ICON |
SHGFI_SMALLICON ); //获取文件图标
DestroyIcon(shInfo.hIcon);
nIcon = shInfo.iIcon; //获取文件图标索引
SetItem(nItem,0,LVIF_IMAGE,"",nIcon,0,0,0); //设置视图项图标
//设置项目标记,0表示文件,1表示目录
if (flFind.IsDirectory())
{
SetItemData(nItem,1);
}
else
{
SetItemData(nItem,0);
}
nItem++;
}
}
}
else //显示FTP服务器信息{
CFtpConnection* pFTP = NULL; //定义FTP连接对象指针
//登录FTP服务器
pFTP =
m_Session.GetFtpConnection(m_FtpServer,m_User,m_Password,atoi(m_Port));
pFTP->SetCurrentDirectory(""); //设置但前目录
CFtpFileFind Find(pFTP); //定义FTP文件查找对象
BOOL bFind; //记录查找结果
m_CurDir =lpPath; //设置当前目录
if (strlen(lpPath)==0)
bFind = Find.FindFile(NULL,INTERNET_FLAG_EXISTING_CONNECT|
INTERNET_FLAG_RELOAD); //从FTP根目录开始查找
else
bFind = Find.FindFile(lpPath,INTERNET_FLAG_EXISTING_CONNECT|
INTERNET_FLAG_RELOAD); //查找指定目录if (bFind) //查找是否成功
{
CString csFileName,csDataTime,csFileSize;
while (bFind ) //遍历当前目录
{
bFind = Find.FindNextFile(); //查找下一个文件
csFileName = Find.GetFileName(); //获取文件名称
CTime fileTime;
Find.GetLastWriteTime(fileTime); //获取文件修改时间
//格式化文件修改时间
csDataTime = fileTime.Format("%Y-%m-%d %H:%M");
if ( !Find.IsDots() && !Find.IsHidden())
{
__int64 lFileLen = Find.GetLength64(); //获取文件长度
if (Find.IsDirectory()) //判断是否为目录
{
csFileSize = "文件夹";
}
else //如果是文件
{
double fGB = lFileLen /(double)(1024*1024*1024);
if (fGB < 1) //是否小于1GB
{
double fMB = lFileLen / (double)(1024*1024);
if (fMB < 1) //是否小于1MB
{
double fBK = lFileLen / (double)(1024);
if (fBK >1) //是否小于1KB
{
csFileSize.Format("%2.2f KB",fBK);
}
else //以位为单位显示
{
csFileSize.Format("%i B",lFileLen);
}
}
else
{
csFileSize.Format("%2.2f MB",fMB);
}
}
else
{
csFileSize.Format("%2.2f GB",fGB);
}
}
}
int nItem = AddItem(csFileName,csFileSize,csDataTime);//添加视图项
//设置文件显示的图标
SHFILEINFO shInfo; //定义文件外壳信息
int nIcon = 0;
CString csName = Find.GetFileName(); //获取文件名
int nPos = csName.ReverseFind('.'); //查找扩展名
if (nPos >0) //如果是文件
{
//映射为本地系统的文件图标
SHGetFileInfo(csName ,FILE_ATTRIBUTE_NORMAL,&shInfo,sizeof(shInfo),
SHGFI_ICON |
SHGFI_SMALLICON|SHGFI_USEFILEATTRIBUTES );
}
else //如果是目录
{
char chPath[MAX_PATH] = {0};
GetCurrentDirectory(MAX_PATH,chPath); //获取当前目录SHGetFileInfo(chPath,FILE_ATTRIBUTE_NORMAL,&shInfo,sizeof(shInfo),
SHGFI_ICON | SHGFI_SMALLICON); //获取目录图标
}
DestroyIcon(shInfo.hIcon);
nIcon = shInfo.iIcon; //获取图标索引
SetItem(nItem,0,LVIF_IMAGE,"",nIcon,0,0,0); //设置视图项显示的图标
//设置项目标记,0表示文件,1表示目录
if (Find.IsDirectory())
{
SetItemData(nItem,1); //设置视图项标记
}
else
{
SetItemData(nItem,0); //设置视图项标记
}
}
}
Find.Close(); //关闭文件查找对象
pFTP->Close(); //关闭FTP文件连接
delete pFTP; //释放FTP连接对象}
}
10)处理列表视图控件的双击事件,如果用户双击的是目录项目,则进入子目录。代码首先判断当前列表视图显示的是本地系统目录信息,还是FTP服务器目录信息。以显示本地系统目录信息为例,首先获取当前视图项关联的整数值,来区分当前视图项表示的是文件还是目录,如果是目录,则获取该目录的完整路径,将其作为参数传递到DisplayPath 方法中以显示直接子目录和文件。
void CSortListCtrl::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult)
{
int nItem = GetSelectionMark(); //获取当前选中的视图项索引
if (nItem != -1)
{
if (m_nListType==0) //进入本地系统子目录
{
int nFlag =GetItemData(nItem); //获取视图项关联的整数值
if (nFlag==1) //判断是否为目录
{
//获取完整的目录信息
CString csFoder = GetItemText(nItem,0);
csFoder += "\\";
//获取目录
m_CurDir += csFoder;
DisplayPath(m_CurDir); //进入子目录
}
}
else //进入FTP服务器子目录
{
int nFlag =GetItemData(nItem); //获取视图项关联的整数值
if (nFlag==1) //判断是否为目录
{
//获取完整的目录信息
CString csFoder = GetItemText(nItem,0);
csFoder += "/";
//获取目录
m_CurDir += csFoder;
DisplayPath(m_CurDir); //进入子目录
}
}
}
*pResult = 0;
}
(11)处理列表视图的WM_KEYDOWN消息,当用户按“Back Space”键时返回上一级目录。代码首先判断列表视图显示的是本地系统目录还是FTP服务器目录,如果是本地系统目录,则根据当前目录获取上一级目录,然后调用DisplayPath方法显示上一级目录。如果是FTP服务器目录,仍然根据当前目录获取上一级目录,只是FTP服务器的目录格式与本地系统的目录格式不同,最后调用DisplayPath方法显示上一级目录。
void CSortListCtrl::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
if (pLVKeyDow->wVKey==VK_BACK) //返回上一级目录
{
if (m_nListType == 0) //显示本地系统目录
{
if (m_BaseDir != m_CurDir && m_BaseDir != "") //如果为根目录则取消操作
{
if ( m_CurDir.Right(1) == "\\" )
{
//去除"\\"
m_CurDir = m_CurDir.Left(m_CurDir.GetLength()-1);
}
int nPos = m_CurDir.ReverseFind('\\');
m_CurDir = m_CurDir.Left(nPos); //返回上级目录
}
}
else //显示FTP服务器目录
{
CString csTmpDir = m_CurDir;
CString csTmpBase = m_BaseDir;
//去除字符串两端的/符号
if (csTmpDir.Right(1)=="/")
csTmpDir = csTmpDir.Left(csTmpDir.GetLength()-1);
if(csTmpDir.Left(1)=="/")
csTmpDir = csTmpDir.Mid(1);
if (csTmpBase.Right(1)=="/")
csTmpBase = csTmpBase.Left(csTmpBase.GetLength()-1);
if(csTmpBase.Left(1)=="/")
csTmpBase = csTmpBase.Mid(1);
if (csTmpBase == csTmpDir ) //如果当前目录已是根目录,则退出
{
return;
}
if (m_CurDir != "")
{
if ( m_CurDir.Right(1) == "/" ) //目录是否以“/”结尾{
//去除/符号
m_CurDir = m_CurDir.Left(m_CurDir.GetLength()-1);
}
int nPos = m_CurDir.ReverseFind('/'); //反向查找/符号
if (nPos != -1)
m_CurDir = m_CurDir.Left(nPos) + '/';//获取上级目录
else
m_CurDir = "";
}
}
DisplayPath(m_CurDir); //显示上级目录
}
*pResult = 0;
}
(12)添加全局函数IsNumber,判断文本是否为数字。因为在排序列时,首先按数字大小排序。
//判断文本是否为数据
bool IsNumber( LPCTSTR pszText )
{
for( int i = 0; i < lstrlen( pszText ); i++ ) //遍历每一个字符
if( !_istdigit( pszText[ i ] ) ) //判断是否是否为数值
return false;
return true;
}
(13)添加CompareDataAsNumber全局函数,用于进行数值比较。对于排序函数来说,如果第一项位于第二项之前,比较函数需要返回一个负数,如果第一项位于第二项之后,比较函数需要返回一个整数。如果两个项相等,比较函数需要返回零值。
int CompareDataAsNumber( LPCTSTR pszParam1, LPCTSTR pszParam2 )
{
int nNumber1 = atoi( pszParam1 );
int nNumber2 = atoi( pszParam2 );
return nNumber1 - nNumber2;
}
(14)添加全局函数IsDate,判断文本是否为日期。日期格式需要采用“2008-08-08”的形式。
//判断是否为日期
bool IsDate( LPCTSTR pszText )
{
//格式为0000-00-00
if( lstrlen( pszText ) < 10 )
return false;
return _istdigit( pszText[ 0 ] ) //判断年部分是否合法
&& _istdigit( pszText[ 1 ] )
&& _istdigit( pszText[ 2 ] )
&& _istdigit( pszText[ 3 ] )
&& pszText[ 4 ] == _T('-')
&& _istdigit( pszText[ 5 ] ) //判断月部分是否合法
&& _istdigit( pszText[ 6 ] )
&& pszText[ 7 ] == _T('-')
&& _istdigit( pszText[ 8 ] ) //判断日部分是否合法
&& _istdigit( pszText[ 9 ] );
}
(15)添加CompareDataAsDate全局函数,进行日期比较。日期的比较是按年、月、日的先后顺序进行计较。
//按日期比较数据
int CompareDataAsDate( const CString& strDate1, const CString& strDate2 )
{
//先比较年
int nYear1 = atoi( strDate1.Mid(0, 4 ) );
int nYear2 = atoi( strDate2.Mid(0, 4 ) );
if (nYear1 != nYear2) //如果年不相等,直接得出了日期的大小
{
return nYear1 - nYear2;
}
//比较月
int nMonth1 = atoi( strDate1.Mid( 5, 2 ) );
int nMonth2 = atoi( strDate2.Mid( 5, 2 ) );
if( nMonth1 != nMonth2 ) //如果年相等,月不相等得出日期的大小
{
return nMonth1 = nMonth2;
}
//比较日
int nDay1 = atoi( strDate1.Mid( 8, 2 ) );
int nDay2 = atoi( strDate2.Mid( 8, 2 ) );
if( nDay1 != nDay2 ) //年和月相等,进行日的比较
return nDay1 - nDay2;
}
return 0; //日期相等,返回0
}
(16)向CSortListCtrl 类中添加静态成员函数SortFunction,用于进行列排序。这里需要注意的是函数的前两个参数,这两个参数将为两个视图项关联的数据,如果视图项没有数据关联,则参数为0,之前在加载视图项时,会为视图项关联一个CItemData结构数据,其作用就在于此。
int CALLBACK CSortListCtrl::SortFunction( LPARAM lParam1, LPARAM lParam2, LPARAM lParamData )
{
CSortListCtrl* pListCtrl = ( CSortListCtrl* )( lParamData );
CItemData* pParam1 = ( CItemData* )( lParam1 );
CItemData* pParam2 = ( CItemData* )( lParam2 );
//获取排序列的文本
LPCTSTR pszText1 = pParam1->m_ColumnTexts[ pListCtrl->m_nSortColumn ];
LPCTSTR pszText2 = pParam2->m_ColumnTexts[ pListCtrl->m_nSortColumn ];
if( IsNumber( pszText1 ) ) //按数值比较
return pListCtrl->m_bAscend ? CompareDataAsNumber( pszText1, pszText2 ) :
CompareDataAsNumber( pszText2, pszText1 );
else if( IsDate( pszText1 ) ) //按日期比较
return pListCtrl->m_bAscend ? CompareDataAsDate( pszText1, pszText2 ) :
CompareDataAsDate( pszText2, pszText1 );
else //按文本比较
return pListCtrl->m_bAscend ? lstrcmp( pszText1, pszText2 ) : lstrcmp( pszText2, pszText1 );
}
(17)向CSortListCtrl 类中添加Sort方法,调用列表视图的SortItems方法对某一列进行升序或降序排序。
void CSortListCtrl::Sort( int iColumn, BOOL bAscending )
{
m_nSortColumn = iColumn; //设置排序列
m_bAscend = bAscending; //设置升序后降序排列
m_ctlHeader.SetSortColomn( m_nSortColumn, m_bAscend );
SortItems( SortFunction, (DWORD)this ); //进行列排序}
(18)处理列表视图控件列的单击事件,当用户单击某一列时,对列进行排序。
void CSortListCtrl::OnColumnClick( NMHDR* pNMHDR, LRESULT* pResult )
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
int nColumn = pNMListView->iSubItem; //获取当前列
//对列进行排序
Sort( nColumn, nColumn == m_nSortColumn ? !m_bAscend : TRUE );
*pResult = 0;
}
(19)改写列表视图控件的PreSubclassWindow方法,将自定义的列表控件关联到列表视图控件中。
void CSortListCtrl::PreSubclassWindow()
{
ASSERT( GetStyle() & LVS_REPORT );
CListCtrl::PreSubclassWindow();
VERIFY( m_ctlHeader.SubclassWindow( GetHeaderCtrl()->GetSafeHwnd() ) );
}
至此,完成了列表视图控件主要功能的设计(在列表视图控件销毁时需要释放项目关联的数据结构,由于篇幅限制,这里没有给出相关代码,详细代码请参考光盘程序)。
1.2 登录FTP服务器
在进行与FTP有关的操作前,首先需要登录FTP服务器才能进行其他相关操作。在MFC中提供有CInternetSession类用于连接网络服务器。通过调用CInternetSession类GetFtpConnection方法可以连接FTP服务器,获取一个与FTP服务器关联的CFtpConnection 对象指针。主要代码如下:
CString csServer,csPassword,csUser,csPort;
m_ConnectBar.GetDlgItemText(IDC_FTPSERVER,csServer); //获取FTP服务器IP
m_ConnectBar.GetDlgItemText(IDC_FTPPORT,csPort); //获取FTP服务器端口
m_ConnectBar.GetDlgItemText(IDC_PASSWORD,csPassword); //获取登录密码m_ConnectBar.GetDlgItemText(IDC_USER,csUser); //获取用户名
if ( !csServer.IsEmpty() && !csPassword.IsEmpty() &&
!csUser.IsEmpty() && !csPort.IsEmpty()) //判断登录信息是否为空
{
try
{
//开始登录服务器
m_pFtp = Session.GetFtpConnection(csServer,csUser,csPassword,atoi(csPort));
m_bLoginSucc = TRUE;
}
catch(CInternetException &e) //进行异常捕捉
{
m_bLoginSucc = FALSE; //登录失败
delete m_pFtp;
}
delete m_pFtp; //释放FTP连接对象}
1.3 实现FTP目录浏览
在登录服务器之后,需要将FTP服务器上的目录和文件信息显示在本地的窗口中,这就需要实现浏览FTP目录。
为了查找FTP服务器上的目录和文件,MFC提供了CFtpFileFind类,该类与CFileFind 类的作用、用法几乎相同,使用FindFile开始查找一个文件,使用FindNextFile方法查找下一个文件。只是CFtpFileFind类用于搜索FTP服务器。此外,在定义一个CFtpFileFind类对象时,需要关联的一个FTP服务器的连接。下面给出实现FTP目录浏览的关键代码。
CFtpConnection* pFTP = NULL; //定义FTP连接对象指针
//登录FTP服务器
pFTP = m_Session.GetFtpConnection(m_FtpServer,m_User,m_Password,atoi(m_Port));
pFTP->SetCurrentDirectory(""); //设置但前目录
CFtpFileFind Find(pFTP); //定义FTP文件查找对象
BOOL bFind; //记录查找结果
m_CurDir =lpPath;
if (strlen(lpPath)==0)
bFind = Find.FindFile(NULL,INTERNET_FLAG_EXISTING_CONNECT|
INTERNET_FLAG_RELOAD); //从FTP根目录开始查找else
bFind = Find.FindFile(lpPath,INTERNET_FLAG_EXISTING_CONNECT|
INTERNET_FLAG_RELOAD); //查找指定目录
FTP上传常见问题 1、为什么无法上传,提示密码不对? 请查看您的登陆名密码填写是否正确?因为如果密码是复制的话,可能会复制出空格。另外,我们给您的初始密码是个英文的,也许是字母l被认为是数字1,字母O被认为是数字0。最后,您要看一下您在ftp登陆时选择的登陆类型是否是普通。 2、为什么无法上传网页,FTP故障-提示“无法连接服务器”错误? 问题出现几种原因:FTP客户端程序设置问题,客户上网线路问题,FTP服务器端问题。处理方法:建议您使用CUTPFTP软件来上传客户的网页,在“FTP主机地址处”最好填写IP 地址,如果您上传时提示socket错误的话,请您检查一下您使用软件的编辑菜单下的连接中防火墙里是否有一个使用了pasv模式?如果选中的话,您把此选项取消即可连接主机。 再检查FTP软件的端口是否设置为默认的21,FTP主机设置是否正确,最后查一下您是否使用了某些防火墙或网关代理软件,看这些软件是否将FTP的21端口屏蔽掉了(如果是默认选择,请把它取消)。如果以上都没问题,请与我公司联系。 3、为什么FTP时已经通过身份验证,但总列不出目录? 问题出现原因:您使用的上传软件的FTP客户端程序不应该选用PASV mode和firewall setting 处理方法:建议使用Cuteftp4.2软件,在Edit->Setting…->Connection->Firewall去掉”PASV mode”这个选项即可。FTP能登录,但里面目录无法显示是因为我们加装了防火墙的原因。请把上传软件的PASV模式关掉,在上传软件的属性里去掉PASV模式,因为这个选项默认是打勾的,去掉就可以了。 4、为什么无法上传,提示连接时找不到主机? 首先请您检查一下您的域名是否做过域名解析?检测方法:您可以在DOS提示符下输入ping域名如果可以ping通的话,则您可以在FTP软件中“FTP主机地址处”填写您的域名,如果ping不通的话,则您需要在“FTP主机地址处”填写您主机的IP地址。如果提示FTP 地址写错:检查FTP地址是否正确,特别是检查最近FTP地址是否有变更过 5、我的网站FTP密码验证可通过,只是在最后不能目录列表列出,显示:LLIST425,这是什么原因? 原因是由于您的虚拟主机空间已用完造成的,请使用FTP登陆,删除一些不必要的文件即可。 6、上传的文件超过我的磁盘限额会出现什么情况? 您将得到系统提示,无法再上传任何东西(文件上传后的字节数为零)。 7、上传网页后,访问结果为”Forbidden”(禁止访问),是什么原因? 问题出现原因:这种结果是由于您相应的目录下,缺少一个索引文件,其名称必须是index.html,index.htm或index.shtml中的一个,缺少索引文件,服务器就会出这种提示,以避免别人看到您的目录下有哪些文件。 处理方法:请您将文件名改成index.html即可。
注意:mput上传可以带目录,put只上传文件,但put上传只能上传登录ftp 前停留的目录。mput上传的文件路径,用户必须有访问权限。否则无法上传。 #!/bin/sh echo>/home/oracle/ftp/Thu_ftp rq=$(date +%Y%m%d) find /u01/backup/data/ora_rman_backup/ticket1/Thu/log/ | grep $rq> /home/oracle/ftp/Thu_ftp echo "open 192.168.248.106" >>/home/oracle/ftp/ftpcmd echo "user ftp Sports-BsT_BeiJing ">>/home/oracle/ftp/ftpcmd awk '{print "prompt mput ",$0;}' ftpfile>>/home/oracle/ftp/ftpcmd echo "quit">>/home/oracle/ftp/ftpcmd echo>/home/oracle/ftp/ftp.out ftp -ivn
文件传送常用的三种方式FTP、Email及“网上邻居”都在一定程度上实现了文件数据的交流,但它们都主要面向“点对点”的传送,无法实现“一块空间,资源互见”的应用需求,这种基于“点对多”的共享模式需要寻求另外的传输途径,网络硬盘就是一种很好的解决方式。 常用传输方式及其在特定环境下面临的困难 我们经常有这样的应用需求:通过网络交换公共数据文件以实现资源共享,同时保护私有数据不被非法访问,并使用简单、直观的方式操作。我们常用的文件传输FTP、Email邮件、网上邻居都能实现文件的传送。其中,"Ftp"功能最为强大,但使用起来却稍显复杂,一大堆设置足以让许多人望而止步,尤其用户数量不可预见时,针对特殊需求用户的设置将更加繁琐;"Email"是大家所熟悉的了,但它的传送不仅需要你连入Internet,而且它的安全性也是个问题,在企业内部,财务、劳资等文件资料需通过这种方式交流不是好办法;"网上邻居"是又一种传送文件的方法,通过在本机上指定共享的Web文件夹并放置资源文件,一定范围内的用户可以访问到这些文件,然而这种方式使用的范围相当有限,通常在同一个DNS段地址内的用户才能顺利访问,其它尤其是Internet上的用户,很难使用,此外同Email类似,它的使用也不直观,很多时候你不得不在许多列表计算机上一层层展开搜索才有可能获取你想要的资源! 由此看来,以上三种方式虽然在一定程度上实现了文件数据的交流,但它们都主要面向"点对点"的传送(你只能被动地等对方放置数据而不能主动"可视化"地索取),无法实现"一块空间,资源互见"的应用需求,这种基于"点对多"的共享方式需要寻求另外的传输途径,网络硬盘就是一种很好的解决方式。 网络硬盘的优势 网络硬盘(也称共享空间),是服务器上的一块硬盘空间,在这里,如果你具备足够的权限,你可以对它随意操作,就象使用你的本地计算机一样。要知道,这一切以Http的方式传输,以Web的形式展现在所有用户面前,通过浏览器这种熟悉的方式访问,这样,"一块空间,资源互见"的共享模式得以实现!
FTP协议分析与源码阅读 一、什么是FTP协议 Transfer Protocal),是文件传输协议的简称。用于Internet上的控制文件的双向传输。同时,它也是一个应用程序(Application)。用户可以通过它把自己的PC机与世界各地所有运行FTP协议的服务器相连,访问服务器上的大量程序和信息。 Transfer Protocol) 1、FTP的作用: 正如其名所示:FTP的主要作用,就是让用户连接上一个远程计算机(这些计算机上运行着FTP服务器程序)察看远程计算机有哪些文件,然后把文件从远程计算机上拷到本地计算机,或把本地计算机的文件送到远程计算机去。 2、FTP工作原理 拿下传文件为例,当你启动FTP从远程计算机拷贝文件时,你事实上启动了两个程序:一个本地机上的FTP客户程序:它向FTP服务器提出拷贝文件的请求。另一个是启动在远程计算机的上的FTP服务器程序,它响应你的请求把你指定的文件传送到你的计算机中。FTP采用“客户机/服务器”方式,用户端要在自己的本地计算机上安装FTP客户程序。FTP 客户程序有字符界面和图形界面两种。字符界面的FTP的命令复杂、繁多。图形界面的FTP 客户程序,操作上要简洁方便的多。简单地说,支持FTP协议的服务器就是FTP服务器,下面介绍一下什么是FTP协议(文件传输协议) 一般来说,用户联网的首要目的就是实现信息共享,文件传输是信息共享非常重要的一个内容之一。Internet上早期实现传输文件,并不是一件容易的事,我们知道Internet是一个非常复杂的计算机环境,有PC,有工作站,有MAC,有大型机,据统计连接在Internet 上的计算机已有上千万台,而这些计算机可能运行不同的操作系统,有运行Unix的服务器,也有运行Dos、Windows的PC机和运行MacOS的苹果机等等,而各种操作系统之间的文件交流问题,需要建立一个统一的文件传输协议,这就是所谓的FTP。基于不同的操作系统有不同的FTP应用程序,而所有这些应用程序都遵守同一种协议,这样用户就可以把自己的文件传送给别人,或者从其它的用户环境中获得文件。 与大多数Internet服务一样,FTP也是一个客户机/服务器系统。用户通过一个支持FTP 协议的客户机程序,连接到在远程主机上的FTP服务器程序。用户通过客户机程序向服务器程序发出命令,服务器程序执行用户所发出的命令,并将执行的结果返回到客户机。比如说,用户发出一条命令,要求服务器向用户传送某一个文件的一份拷贝,服务器会响应这条命令,将指定文件送至用户的机器上。客户机程序代表用户接收到这个文件,将其存放在用户目录中。 在FTP的使用当中,用户经常遇到两个概念:"下载"(Download)和"上载"(Upload)。"下载"文件就是从远程主机拷贝文件至自己的计算机上;"上载"文件就是将文件从自己的计算机中拷贝至远程主机上。用Internet语言来说,用户可通过客户机程序向(从)远程主机上载(下载)文件。 使用FTP时必须首先登录,在远程主机上获得相应的权限以后,方可上载或下载文件。也就是说,要想同哪一台计算机传送文件,就必须具有哪一台计算机的适当授权。换言之,除非有用户ID和口令,否则便无法传送文件。这种情况违背了Internet的开放性,Internet 上的FTP主机何止千万,不可能要求每个用户在每一台主机上都拥有帐号。匿名FTP就是为解决这个问题而产生的。 匿名FTP是这样一种机制,用户可通过它连接到远程主机上,并从其下载文件,而无
完整程序FTP上传 package com.zhcw.update.msisdn; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import https://www.doczj.com/doc/8312333506.html,.TelnetInputStream; import https://www.doczj.com/doc/8312333506.html,.TelnetOutputStream; import https://www.doczj.com/doc/8312333506.html,.ftp.FtpClient; /** * Title: FTP上传功能类 * Description: FTP上传功能类 * Copyright: Copyright (c) 2012 * Company: 北京世纪国彩科技有限公司 * * @author chenchuang * @version 1.0 */ public class FtpUtil { private String ip=""; private String username=""; private String password=""; private int port=-1; private String path=""; FtpClient ftpClient=null; OutputStream os=null; FileInputStream is=null; public FtpUtil(String serverIp ,String username,String password){ this.ip=serverIp; https://www.doczj.com/doc/8312333506.html,ername=username; this.password=password; } public FtpUtil(String serverIp , int port,String username,String password){
Leapftp上传软件教程 Leapftp是一种常用的上传工具软件。她和cuteftp一样好用、功能强大、媲美Bullet Proof FTP的FTP软件。跟Netscape相仿的书签形式,连线更加方便。下载与上传文件支持续传。可下载或上传整个目录,亦可直接删除整个目录。可让你编列顺序一次下载或上传同一站台中不同目录下的文件。浏览网页时若在文件连结上按鼠标右键选[复制捷径]便会自动下载该文件。具有不会因闲置过久而被站台踢出的功能。可直接编辑远端Server上的文件。可设定文件传送完毕自动中断Modem连接。 下面教大家如何使用它: 1.请先点这里下载并安装LeapFTP最新版本。您也可使用其它FTP工具,请直接参考下面的设置方法。 2. 运行LeapFTP,点击1处(站点->站点管理器),弹出“站点管理器”窗口;在2处点击“添加站点”按钮,在弹出的窗口3处输入您喜欢的站点名称(如:https://www.doczj.com/doc/8312333506.html,); 3.点击“确定”后,出现以下界面。在1处输入您的站点地址(服务器IP:如:218.5.76.121),将2处“匿名”前的选钩去掉,在3处输入FTP用户名(如:zgmw),在4处输入FTP密码(将保存密码前的选钩打上),点击5处“应用”按钮;
4.点击上图6 处,切换到“高级”标签(如下图)。在1处选中刚建立的站点名称(https://www.doczj.com/doc/8312333506.html,),在2处的“传送模式”选择二进制,点击3处“应用”。至此您的FTP站点已经建立成功; 5.连接成功后的界面如下图所示。左上框为本地目录,您可以通过1 处的下拉菜单选择您要上传文件的目录,选择后该目录下的所有文件都会显示在这个框里。选择您要上传的文件,并点鼠标“右链”->“上传”,这时在队列栏里会显示正在上传及未上传的文件,当您的文件上传成功完成后,在命令栏里会出现“传送完成”的提示,此时在过程目录栏里就可以看到您上传的文件了。
如何使用ftp上传文件.txt举得起放得下叫举重,举得起放不下叫负重。头要有勇气,抬头要有底气。学习要加,骄傲要减,机会要乘,懒惰要除。人生三难题:思,相思,单相思。FTP新手入门及构建个人FTP服务器从O开始 FTP简介 FTP的全称是File Transfer Protocol(文件传输协议)。顾名思义,就是专门用来传输文件的协议。而FTP服务器,则是在互联网上提供存储空间的计算机,它们依照FTP协议提供服务。当它们运行时,用户就可以连接到服务器上下载文件,也可以将自己的文件上传到FTP 服务器中。因此,FTP的存在,大大方便了网友之间远程交换文件资料的需要,充分体现了互联网资源共享的精神。现在许多朋友都已经用上了宽带网,而且硬盘也有足够的空间,完全可以通过软件手段把自己的电脑变为一台FTP服务器,和网络中的朋友们一起分享大家各自收藏的好东东! 架设FTP服务器,其实并没有技术难度,只需用Serv-U这个软件就可轻松搞定了。Serv-U 支持所有版本的Windows操作系统,可以设定多个FTP服务器,可以限定登录用户的权限、登录目录及服务器空间大小,功能非常完善。以下笔者就以Serv-U汉化版为例,给大家讲讲架设个人FTP的具体步骤。 首先下载安装Serv-U,运行,将出现“设置向导”窗口,我们就来跟随着这个向导的指引,一步步进行操作。 1. 设置Serv-U的IP地址与域名 一路单击“下一步”跳过系统提示信息,来到“您的IP地址”窗口,这里要求输入本机的IP地址。 如果你的电脑有固定的IP地址,那就直接输入;如果你只有动态IP(例如拨号用户),那该处请留空,Serv-U在运行时会自动确定你的IP地址。 下一步,进行“域名”设定。这个域名只是用来标识该FTP域,没有特殊的含义,比如笔者输入“https://www.doczj.com/doc/8312333506.html,”。 接下来的“系统服务”选项必须选“是”,这样当你的电脑一启动,服务器也会跟着开始运行。 2.设置匿名登录 匿名访问就是允许用户以Anonymous为用户名,无需特定密码即可连接服务器并拷贝文件。如果你不想让陌生人随意进入你的FTP服务器,或想成立VIP会员区,就应该在“匿名账号”窗口中选“否”,这样就只有经过你许可的用户才能登录该FTP。鉴于匿名登录尚有一定的实用需求,笔者在此选“是”。 之后就要为匿名账户指定FTP上传或下载的主目录,这是匿名用户登录到你的FTP服务器后看到的目录。设定后,向导还会继续询问你是否将匿名用户锁定于此目录中,从安全的角度考虑,建议选“是”。这样匿名登录的用户将只能访问你指定的主目录及以下的各级子目录,
VC实现文件上传下载(FTP) //连接ftp服务器 void CMyFtpDlg::OnConnect() { UpdateData(TRUE); //新建对话 m_pInetSession=new CInternetSession(AfxGetAppName(),1,PRE_CONFIG_INTERNET_AC CESS); try { //新建连接对象 m_pFtpConnection=m_pInetSession-> GetFtpConnection(m_strServer,m_strUserName, m_strPassword); } catch(CInternetException *pEx) { //获取错误 TCHAR szError[1024]; if(pEx-> GetErrorMessage(szError,1024)) AfxMessageBox(szError); else AfxMessageBox( "There was an exception "); pEx-> Delete(); m_pFtpConnection=NULL; return; } m_pRemoteFinder = new CFtpFileFind(m_pFtpConnection); //获得服务器根目录的所有文件并在列表框中显示 BrowseDir( " ",&m_ctrlRemoteFiles,m_pRemoteFinder,&m_arrRemoteFiles); } //下载单个文件 void CMyFtpDlg::DownFile(FILEITEM fileItem) { if(fileItem.bDir == TRUE) { AfxMessageBox( "本程序暂时不支持下载整个文件夹,请选择文件下载"); } else { //格式化文件名
FTP上传下载方式有以下几种 1.Windows下免费开源的FTP客户端软件FileZilla,在/public/softwares下有64位和32位版本。 2.Windows下流行的商业软件FlashFXP、SmartFTP,软件位于/public/softwares 3.Linux中GNOME桌面环境中运行的FTP客户端软件:gftp,软件位于/public/softwares 4.使用FTP命令:步骤如下 (1)“开始”-“运行”-输入“FTP”回车 (2)open 123.57.37.107 回车 (3)/*命令行会提示你输入用户名,不同的OS版本(XP,Vista,Win7)提示可能会有所差别*/ (4)/*提示你输入密码,在密码输入过程中不会显示也不会移动光标,打完密码后回车即可。如果你的密码输入错误,将不会提示你重新输入,这时你要键入“user”命令,将会出现第三步,你可 以重新输入用户名和密码。*/ (5)cd public /*进入public文件夹*/ (6)dir /*你成功登陆后就可以用dir查看命令查看FTP服务器中的文件及目录,用ls命令只可以查看文件。*/ (7)mkdir rsfile /*在FTP服务器上根目录下建立rsfile目录。*/ (8)cd rsfile /*进入目录rsfile,用“cd 你的目录名”可以进入当前目录的下一级目录,这跟DOS一样。*/ (9)bin /*采用二进制传输。如果你要上传下载,这一步很重要,不先执行这个命令,上传下载会很慢。*/ (10)lcd D:\ftpin /*定位本地默认文件夹。这里的lcd命令类似于平时命令行下的cd*/
简单上传下载实例(/*....*/为注释): 先假设有一FTP服务器,FTP服务器:https://www.doczj.com/doc/8312333506.html,,用户名:username 密码:user1234。在本地电脑D:盘创建一个文件夹"qint"。将要上传的文件复制到d:\qint里。通过FTP命令将文件从本地上传,从服务器下载的步骤如下: 1.“开始”-“运行”-输入“FTP” 2.open https://www.doczj.com/doc/8312333506.html, /*这一步可以与第一步合并,在“运行”里直接输入"ftp https://www.doczj.com/doc/8312333506.html,"。如果你的FTP服务器不是用的21默认端口,假如端口是2121,那么此步的命令应在后面空格加2121,即“open https://www.doczj.com/doc/8312333506.html, 2121”*/ https://www.doczj.com/doc/8312333506.html,ername /*提示你输入用户名*/ https://www.doczj.com/doc/8312333506.html,er1234 /*提示你输入密码,密码不回显,打完密码后回车即可。如果你的密码输入错误,将不会提示你重新输入,这时你要键入“user”命令,将会出现第三步,你可以重新输入用户名和密码。*/ 5.dir /*你成功登陆后就可以用dir查看命令查看FTP服务器中的文件及目录,用ls命令只可以查看文件。*/ 6.mkdir qint /*在FTP服务器上根目录下建立qint目录。*/
7.cd qint /*进入目录qint,用“cd 你的目录名”可以进入当前目录的下一级目录,这跟DOS一样。*/ 8.bin /*采用二进制传输。如果你要上传下载,这一步很重要,不先执行这个命令,上传下载会很慢。*/ 9.lcd d:\qint /*定位本地默认文件夹,在前面我事先在D:盘创建的。*/ 10.!dir /*查看本地文件夹中的文件及目录*/ 11.put i001.jpg /*将当前目录(d:\qint)中的文件i001.jpg上传到FTP服务器默认目录。可以用"mput *.*"将所有文件上传到FTP服务器上。*/ 12.get d123.jpg /*将FTP服务器默认目录中的文件d123.jpg下载到当前目录下(d:\qint)。可以用"mget *.*"将所有文件下载到d:\qint*/ 13.delete *.* /*删除目录qint中的所有文件。*/ 14.cd .. /*返回至上一级目录,即根目录。返回上一级目录用“cd ..”要注意,中间有空格。返回根目录用“cd \”。*/ 15.mrdir qint
ckage comm; import java.io.file; import java.io.fileinputstream; import java.io.outputstream; import java.util.stringtokenizer; import https://www.doczj.com/doc/8312333506.html,.ftp.ftpclient; public class ftp { private string ip = ""; private string username = ""; private string password = ""; private int port = 21; private string localfilefullname = "";//需要上传的目录 ftpclient ftpclient = null; outputstream os = null; fileinputstream is = null; public ftp(string serverip, int port , string username, string password) { this.ip = serverip; https://www.doczj.com/doc/8312333506.html,ername = username; this.password = password; this.port = port;
} public ftp(string serverip,string username, string password) { this.ip = serverip; https://www.doczj.com/doc/8312333506.html,ername = username; this.password = password; } private void createdir(string dir, ftpclient ftpclient) throws exception { ftpclient.ascii(); stringtokenizer s = new stringtokenizer(dir, "/"); //sign s.counttokens(); string pathname = ""; while (s.hasmoreelements()) { pathname = pathname + "/" + (string) s.nextelement(); try { ftpclient.sendserver("mkd " + pathname + "\r\n"); } catch (exception e) { e = null; } ftpclient.readserverresponse(); } ftpclient.binary(); } private boolean isdirexist(string dir, ftpclient ftpclient) { try {
通过DOS命令进行FTP上传和下载 例如在北京师范大学多媒体服务器进行操作: FTP Server: https://www.doczj.com/doc/8312333506.html, User: anonymous (匿名登录) Password: 登录 方法一、在Windows的开始菜单下,执行“运行”命令,在对话框中输入ftp,按下“确定”按钮将会切换至DOS窗口,出现命令提示符 ftp> 键入命令https://www.doczj.com/doc/8312333506.html,连接FTP服务器: ftp> https://www.doczj.com/doc/8312333506.html, 方法二、执行“运行”命令,在对话框中输入cmd,切换至DOS窗口,出现命令提示符 C:\Documents and Settings\Administrator> 键入命令ftp https://www.doczj.com/doc/8312333506.html, 连接服务器: C:\Documents and Settings\Administrator>ftp https://www.doczj.com/doc/8312333506.html, 稍等片刻,屏幕提示连接成功: ftp> connected to https://www.doczj.com/doc/8312333506.html, 接下来服务器询问用户名和口令User (https://www.doczj.com/doc/8312333506.html,:(none)): anonymous Password: (无密码直接回车)待认证通过即可。 上传文件: 比如要把c:\test.doc传至服务器的根目录中,可以键入: ftp> put c:\test.doc (回车) 当屏幕提示你已经传输完毕,可以键入相关命令查看: ftp> dir (回车) 下载文件: 假设要把服务器\open目录中的type.txt文件传至本机中,可以输入指令:ftp> cd open(回车) [注:进入\open目录] ftp> type.txt 上传与下载工作完毕,键入bye(quit)中断连接: ftp> bye(回车) 常用的FTP命令: 1. open:与服务器相连接; 2. send(put):上传文件; 3. get:下载文件; 4. mget:下载多个文件; 5. cd:切换目录; 6. dir:查看当前目录下的文件;
#region上传文件 ///
ftp文件上传下载模块概述 1.1 开发背景 如果用户不使用FTP客户端软件,而是直接登录到FTP服务器来上传或下载FTP文件,会存在许多不足。例如,在同时下载多个文件时,如何暂停或继续某个文件的下载,如果下载大量文件,如何在任务下载完成后关闭计算机。这就是FTP客户端软件的作用,也是笔者设计本章程序的主要原因。 1.2 需求分析 FTP文件上传下载模块的主要功能是实现FTP文件的多任务上传、下载,对于实现FTP 文件的上传和下载,可以使用MFC提供的WinInet相关类非常方便地实现,模块的难点在于多任务,需要为每个上传或下载的任务维护一个单独的线程,用户可以暂停和取消任务。在关键技术部分笔者将介绍如何实现FTP文件多任务下载。 1.3 模块预览 FTP文件上传下载模块只包含一个主对话框,但是主对话框却由登录信息栏、工具栏、本地信息窗口、远程FTP服务器信息窗口和任务列表共5个子窗口构成。下面分别给出各个窗口的效果图。 FTP文件上传下载模块主窗口效果图如图1所示。 图1 FTP文件上传下载模块主窗口
登录信息栏效果如图2所示工具栏窗口效果如图3所示。 图3 工具栏窗口 本地信息窗口效果图如图4所示。 图4 本地信息窗口 远程FTP服务器信息窗口效果如图5所示。
任务列表窗口运行效果如图6所示。 图6 任务列表窗口
关键技术 1.1 设计类似于资源管理器的列表视图控件 在设计FTP文件上传下载模块时,首先需要确定采用何种方式显示本地和FTP服务器上的目录和文件。为了模仿Windows资源管理器的效果,笔者采用了列表视图控件——CListCtrl来实现目录和文件的显示。但是,MFC提供的默认的CListCtrl无法实现Windows 资源管理器的效果,我们必须重新设计一个列表视图控件。该控件需要具备的功能有以本地系统默认的图标显示目录和文件的图标,在控件中双击某一个目录将进入子目录,按“Back Space”键将返回上一级目录,实现对某一列的升序、降序排列,并以箭头标识。控件的设计效果如图13.4所示。在设计控件之前,读者需要对CListCtrl控件有所了解。CListCtrl 控件主要有两部分构成,第一部分是列头部分,由CHeaderCtrl控件构成,第二部分是表格部分。当在列头部分绘制排序箭头时,实际上是在CHeaderCtrl控件上进行的。 下面介绍控件的详细设计过程。首先设计列头控件,因为需要绘制排序列的标记。 (1)从CHeaderCtrl类派生一个子类——CSortHeaderCtrl,向该类中添加成员变量。 (1)从CHeaderCtrl类派生一个子类——CSortHeaderCtrl,向该类中添加成员变量。 int m_nSortColumn; //排序列 BOOL m_bAscend; //是否为升序 (2)在构造函数中初始化成员变量。 CSortHeaderCtrl::CSortHeaderCtrl() { m_nSortColumn = -1; m_bAscend = TRUE; } (3)向CSortHeaderCtrl类中添加SetSortColomn方法,用于设置排序列和排序列的自绘风格。 void CSortHeaderCtrl::SetSortColomn(int nColumn, BOOL bAscend) { m_nSortColumn = nColumn; //设置排序列 m_bAscend = bAscend; //设置排序方式 HD_ITEM hItem; hItem.mask = HDI_FORMAT; GetItem( nColumn, &hItem ) ; //获取列信息 hItem.fmt |= HDF_OWNERDRAW; //设置列自绘风格 SetItem( nColumn, &hItem ); //设置列信息 Invalidate(); //更新控件 }
Ftp 判断文件是否上传成功批处理 开下面这个批处理是否能实现你的要求, 从另一台ftp 去判断@echo off rem 指定FTP 用户名 set ftpUser=asx rem 指定FTP 密码 set ftpPass=asx-asx rem 指定FTP 服务器地址 set ftpIP=172.19.103.42 rem 指定待下载的文件位于FTP 服务器的什么位置 set ftpFolder=/export/home/PROD/ntcdata rem 指定从FTP 下载下来的文件存放到什么地方 set ntdutbin-st set DownFolder2=D:\AppServ\www\BadDut\data\dutbin\wright \ntdutbin-o set DownFolder3=D:\AppServ\www\BadDut\data\summary\wri ght\ntsummary_st
set DownFolder4=D:\AppServ\www\BadDut\data\summary\wri ght\ntsummary_orem 指定下载几天前的文件 set DaysAgo=1 set ftpDir=%temp%\TempDir.txt set ftpDown=%temp%\TempDown.txtrem 假设本机日期格式为yyyy-mm-dd set FileY=%date:~0,4% call :DateToDays %date:~0,4% %date:~5,2% %date:~8,2% PassDays set /a PassDays-=DaysAgo call :DaysToDate %PassDays% DstYear DstMonth DstDay>"%ftpDir%" echo.%ftpUser% >>"%ftpDir%" echo.%ftpPass% >>"%ftpDir%" echo bin >>"%ftpDir%" echo cd "%ftpFolder%" >>"%ftpDir%" echo dir * "%temp%\FileList.txt" >>"%ftpDir%" echo bye start ftp -v -i -s:"%ftpDir%" %ftpIP%rem 根据实际情况自行调节延迟时间 ping -n 350 127.1 >nulfindstr /i ":*\.SWM$" "%temp%\FileList.txt">"%temp%\FileDate.txt" findstr /i ":*\.TWM$" "%temp%\FileList.txt">>"%temp%\FileDate.txt" findstr /i ":*\.OWM$" "%temp%\FileList.txt">>"%temp%\FileDate.txt">"%ftpDow n%" echo.%ftpUser% >>"%ftpDown%" echo.%ftpPass% >>"%ftpDown%" echo bin >>"%ftpDown%" echo cd "%ftpFolder%" (for /f "usebackq tokens=1-9 delims= " %%a in ("%temp%\FileDate.txt") do ( setlocal enabledelayedexpansion if "%%f" equ "Jan" (
1、 一.文件传输FTP、BBS(电子公告板,是远程登录服务中的一种应用形式) 2、接入Internet并且支持FTP协议的两台计算机,对于它们之间的文件传输,下列说法正确的是__C____。 A.只能传输文本文件 B.不能传输图形文件 C.所有文件均能传输 ---- 不同格式的文件均能传输 D.只能传输几种类型的文件 3、在Internet中,用于文件传输的协议是______。C.FTP 4、关于Internet中FTP的说法不正确的是__D____。 A.FTP是Internet上的文件传输协议 B.可将本地计算机的文件传到FTP服务器 C.可在FTP服务器下载文件到本地计算机 D.可对FTP服务器的硬件进行维护 5、下面___B_____是ftp服务器的地址。 A.http://192.163.113.23 ---- 表示WWW服务的网址 B.ftp://61.16.11.2 --- 网址可以直接用IP地址表示也可以用域名表示 https://www.doczj.com/doc/8312333506.html, . D.C.\windows 6、匿名FTP是________。C.允许用户免费登录并下载文件的FTP ---- FTP提供了匿名(不署名)的服务,访问时不需要帐号 7、访问https://www.doczj.com/doc/8312333506.html,服务器下的office目录时,其地址的正确写法是__C____。 https://www.doczj.com/doc/8312333506.html,/office https://www.doczj.com/doc/8312333506.html,\office C.ftp://https://www.doczj.com/doc/8312333506.html,/office D.ftp:\\https://www.doczj.com/doc/8312333506.html,\office 8、用浏览器访问FTP站点,应在主机域名前加入______标志。C.ftp:// 9、将数据从本地计算机中拷贝到远程计算机上,称之为_______。C.上传文件 10、BBS是一种________.C.在互联网可以提供交流平台的公告板服务 11、下列关于BBS的叙述,错误的是__D____。 A.BBS翻译为中文就是"电子公告板" B.BBS的英文全称是Bulletin Board System C.BBS一般都按不同的主题、分主题分成很多个布告栏 D.BBS使用者可以阅读关于某个主题的最新看法,但不能将自已的想法贴到公告栏中 12、以下属于BBS访问方式的是__A____。(请看解析) A.Telnet和WWW B.E-Mail和WWW C.Telnet和Internet Explorer D.Internet Explorer和E-Mail 13、telnet协议的用途是________。A.远程登录 14、下列关于网上交流的说法,错误的是__D____。 A. Telnet(远程登录)可以登录BBS B."博客"是使用特定的软件,在网络上出版、发表和张贴个人文章的人,并实现网上交流。 C.E-MAIL也是一种网上交流形式。
如何使用FTP 概述 FTP是由它使用的应用协议命名的,即文件传送协议[File TransferProtocol],它的作用是把文件从一个计算机转移到另一个计算机.当您启动ftp从远程计算机拷贝文件时,您也是启动了两个程序:您本地机上的ftp客户程序:它提出拷贝文件的请求.另一个是运行在远程计算机上的ftp服务器程序,它响应您的请求把您指定的文件传送到您的计算机。 Internet上有很大一部分ftp服务器被标为"匿名"[Anonymons]ftp服务器.这类服务器的目的是向公众提供文件拷贝服务,因此,不要求用户事先在该服务器进行登记.与这类"匿名"ftp 服务器建立联接时,您一般在"用户名"栏填入"anonymons",而在"密码"栏填上您的电子邮件地址.另一类FTP服务器为非匿名FTP服务器,要进入该类服务前,您必须先向服务器系统管理员申请用户名及密码,非匿名FTP服务器通常供内部使用或提供咨询服务。 匿名FTP是一种最重要、用途最广泛的Internet服务。这种卓越的服务可以使你从Internet 的上千种计算机上拷贝文件。这些储存在计算机上的文件包含着各种各样的信息。 你想为你的PC机获得一个程序吗?你想要一期电子杂志吗?你想向Usenet讨论组频繁提问题吗? Internet中几乎有你所想要的各种资料和计算机软件,你都可以免费地进入并取出。 这一章讲的是怎样使用匿名FTP。也许你不知道怎样进入FTP,我们将告诉你怎样通过电子邮件得到文件。 当你看完这一章,你就能够读第十三章的有关内容了。在第十三章,将讲解怎样运用Archie 服务器在匿名FTP主机上查询大量具体的文件。 FTP简介 “FTP”这个词是文件传送协议的缩写(File Transfer Protocol),FTP是在Internet上传送文件的规定的基础。我们提到FTP时不只是认为它是一套规定,FTP是一种服务,它可以在Internet上,使得文件可以从一台Internet主机传送到另一台Internet主机上,通过这种方式,主要靠FTP把Internet中的主机相互联系在一起。 像大多数的Internet服务一样,FTP使用客户机/服务器系统(参见第二章),你在使用一个名叫ftp的客户机程序时,就和远程主机上的服务程序相连了。理论上讲,这种想法是很简单的。当你用客户机程序时,你的命令就发送出去了,服务器响应你发送的命令。例如,你录入一个命令,让服务器传送一个指定的文件,服务器就会响应你的命令,并传送这个文件;你的客户机程序接收这个文件,并把它存入你的目录中。(在这章的后面将讨论文件和目录问题)。