VC实现文件的上传下载 客户端



//basedef.h

//此头文件定义了结构体和消息


#pragma once
#include <afxsock.h>

#define   WM_FILELIST   WM_USER + 101  //接收文件列表
#define   WM_FILEUPDATE  WM_USER + 102  //反映文件下载状态
#define   WM_FILEDOWNLOAD  WM_USER + 103    //发送文件列表


#define   FILELIST      1000    //请求文件列表
#define   FILEUPDATE   2000    //请求文件上传
#define   FILEDOWNLOAD  3000    //请求文件下载

#define   RECVSIZE   1024*16       //一次性发送/接收的数据块大小

//文件传递结构
typedef struct
{
 int  iCommand;
 long lFileOffset;
 long lFileLength;
 char sFilePath[128];
}MSGFILE;

//请求线程参数
typedef struct
{
 char sIP[15];  //IP地址
 int  iPort;   //端口
 MSGFILE msgFile; //通信语言结构
 LPVOID ptr;  //指针
}MSGPARAM;

//文件列表结构
typedef struct
{
 long lFileLength;
 char sFilePath[128];
}MSGFILELIST;

//反映文件状态的结构
typedef struct
{
 long lFileOffset;//偏移
 char sFilePath[128];//路径
}MSGFILESTATUS;

//接收线程参数
typedef struct
{
 SOCKET sock;
 LPVOID ptr;
}PARAMRECV;


//客户端  文件传输类

//

// Ftp_Client.h: interface for the CFtp_Client class.
//
//

#if !defined(AFX_FTP_CLIENT_H__CB684F7E_C9B5_4025_AA2E_F307234CA75C__INCLUDED_)
#define AFX_FTP_CLIENT_H__CB684F7E_C9B5_4025_AA2E_F307234CA75C__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "basedef.h"

#define WM_CONNECTERROR  WM_USER + 301

class CFtp_Client 
{
public:
 CFtp_Client();
 virtual ~CFtp_Client();


 //创建线程发送请求
 void SendRequest(MSGPARAM msgParam);
 
 //设置服务器参数
 BOOL InitParam(CWnd* pWnd, char* sIP, int nPort);

 //停止所有线程
 void StopThread();
 
protected:
 //请求线程
 static DWORD WINAPI RequestThread(LPVOID lpParam);
 
private:
 //服务器IP
 char m_sIP[15];
 
 //服务器端口
 int m_nPort;
 
 //指向窗口的指针
 CWnd* m_pWnd;

 //停止线程
 static BOOL m_bEndThread;
};

#endif // !defined(AFX_FTP_CLIENT_H__CB684F7E_C9B5_4025_AA2E_F307234CA75C__INCLUDED_)


//cpp 文件

// Ftp_Client.cpp: implementation of the CFtp_Client class.
//
//

#include "stdafx.h"
#include "Ftp_Client.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

BOOL CFtp_Client::m_bEndThread = FALSE;
//
// Construction/Destruction
//

CFtp_Client::CFtp_Client()
{
 strcpy(m_sIP, "127.0.0.1");
 m_nPort = 7000;
 m_pWnd = NULL;
}

CFtp_Client::~CFtp_Client()
{
 
}

BOOL CFtp_Client::InitParam(CWnd* pWnd, char* sIP, int nPort)
{
 if (!AfxSocketInit())
 {
  return FALSE;
 }
 //保留参数
 strcpy(m_sIP, sIP);
 m_nPort = nPort;
 m_pWnd = pWnd;
 
 return TRUE;
}


//向服务器请求文件列表
void CFtp_Client::SendRequest(MSGPARAM msgParam)
{
 //为结构体赋值,作为参数传递到线程
 MSGPARAM* pMsgParam = new MSGPARAM;
 pMsgParam->ptr = m_pWnd;
 strcpy(pMsgParam->sIP, m_sIP);
 pMsgParam->iPort = m_nPort;
 pMsgParam->msgFile.iCommand = msgParam.msgFile.iCommand;
 pMsgParam->msgFile.lFileLength = msgParam.msgFile.lFileLength;
 pMsgParam->msgFile.lFileOffset = msgParam.msgFile.lFileOffset;
 strcpy(pMsgParam->msgFile.sFilePath, msgParam.msgFile.sFilePath);
 
 DWORD id;
 HANDLE h = CreateThread(NULL, 0, RequestThread, pMsgParam, 0, &id);
 //创建发送请求并接收反馈的线程
 CloseHandle(h);
 
}


DWORD WINAPI CFtp_Client::RequestThread(LPVOID lpParam)
{
 MSGPARAM* pMsgParam = (MSGPARAM*)lpParam;
 CWnd* pWnd = (CWnd*)pMsgParam->ptr;
 
 SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
 
 SOCKADDR_IN sin;
 sin.sin_family = AF_INET;
 sin.sin_addr.s_addr = inet_addr(pMsgParam->sIP);
 sin.sin_port = htons(pMsgParam->iPort);
 
 //连接成功
 if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
 {
  //发送请求
  int iSendCnt = send(sock, (char*)&pMsgParam->msgFile, sizeof(pMsgParam->msgFile), 0);
  
  if(pMsgParam->msgFile.iCommand == FILELIST) //如果是请求文件列表
  {
   pWnd->SendMessage(WM_FILELIST, sock, 0);
  }
  else if (pMsgParam->msgFile.iCommand == FILEUPDATE)
  {
   char sRecvBuf[RECVSIZE] = "\0"; //接收缓冲区置空
   long lFileOffset = pMsgParam->msgFile.lFileOffset;
   //打开文件,打不开则不上传
   CFile file;
   BOOL bResult = file.Open(pMsgParam->msgFile.sFilePath, CFile::modeRead|CFile::shareDenyNone, NULL);
   if(bResult)
   {
    char sSendBuf[RECVSIZE];//发送缓冲区,16K
    while(!CFtp_Client::m_bEndThread && lFileOffset < pMsgParam->msgFile.lFileLength)
    {
     int iSeek = file.Seek(lFileOffset, CFile::begin);//寻找新的文件偏移,距离开始处
     int iReadCnt = file.Read(sSendBuf, RECVSIZE);//读计数器,读到发送缓冲区,一次16K
     if (iReadCnt ==0)//读出字节数为0
      break;
     
     int iSendCnt = send(sock, sSendBuf, iReadCnt, 0);
     if (iSendCnt == -1)
      break;
     else
      lFileOffset += iSendCnt;//修改偏移量
     
     MSGFILESTATUS msgFileStatus;//文件状态结构体
     msgFileStatus.lFileOffset = lFileOffset;
     strcpy(msgFileStatus.sFilePath, pMsgParam->msgFile.sFilePath);
     pWnd->SendMessage(WM_FILEUPDATE, (WPARAM)&msgFileStatus, 0);

    }

    file.Close();
   }
  }
  
  else if(pMsgParam->msgFile.iCommand == FILEDOWNLOAD) //如果是请求下载文件
  {
   char sRecvBuf[RECVSIZE] = "\0"; //接收缓冲区置空
   long lFileOffset = pMsgParam->msgFile.lFileOffset;
   CFile file;
   BOOL bResult = file.Open(pMsgParam->msgFile.sFilePath, CFile::modeWrite|CFile::modeNoTruncate, NULL);
   //打开接收端文件,写模式||若创建的文件已存在,不截短。
   while(!CFtp_Client::m_bEndThread && bResult && lFileOffset < pMsgParam->msgFile.lFileLength)
   {
    int iRecvCnt = recv(sock, sRecvBuf, RECVSIZE, 0);
    if(iRecvCnt <= 0)
     break;
    
    file.Seek(lFileOffset, CFile::begin);
    file.Write(sRecvBuf, iRecvCnt);//写到接收缓冲区
    lFileOffset += iRecvCnt;//修改偏移
    
    MSGFILESTATUS msgFileStatus;//文件状态结构体
    msgFileStatus.lFileOffset = lFileOffset;
    strcpy(msgFileStatus.sFilePath, pMsgParam->msgFile.sFilePath);
    pWnd->SendMessage(WM_FILEDOWNLOAD, (WPARAM)&msgFileStatus, 0);
   }
   file.Close();
   
   if(lFileOffset < pMsgParam->msgFile.lFileLength && !CFtp_Client::m_bEndThread)  //如果没有下载完,请求续传
   {//接收线程未结束&&偏移<文件长度
    
    MSGPARAM* pMsgParamResume = new MSGPARAM;//指向请求线程参数结构体的指针
    strcpy(pMsgParamResume->sIP, pMsgParam->sIP);
    pMsgParamResume->iPort = pMsgParam->iPort;
    pMsgParamResume->ptr = pMsgParam->ptr;
    pMsgParamResume->msgFile.iCommand = pMsgParam->msgFile.iCommand ;
    pMsgParamResume->msgFile.lFileLength = pMsgParam->msgFile.lFileLength;
    pMsgParamResume->msgFile.lFileOffset = lFileOffset;
    strcpy(pMsgParamResume->msgFile.sFilePath, pMsgParam->msgFile.sFilePath);
    
    DWORD id;
    HANDLE h = CreateThread(NULL, 0, RequestThread, pMsgParamResume, 0, &id);
    //递归调用
    CloseHandle(h);
   }
  }
 }
 else
 {
  pWnd->SendMessage(WM_CONNECTERROR, 0, 0);
 }
 closesocket(sock);
 delete pMsgParam;
 
 return 0;
}

void CFtp_Client::StopThread()
{
 m_bEndThread = TRUE;
}

//对话框头文件

// Client_FTPDlg.h : header file
//

#if !defined(AFX_CLIENT_FTPDLG_H__E7F99F34_0BD2_4B11_8FF7_D958887D2368__INCLUDED_)
#define AFX_CLIENT_FTPDLG_H__E7F99F34_0BD2_4B11_8FF7_D958887D2368__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "Label.h"
#include "Ftp_Client.h"

/
// CClient_FTPDlg dialog
 
class CClient_FTPDlg : public CDialog
{
// Construction
public:

 void InitListColumn();
 CClient_FTPDlg(CWnd* pParent = NULL); // standard constructor

 CFtp_Client *m_pFtpClient; //上传下载类对象

 BOOL m_bConnected; //连接状态
 long m_lFileSize; //文件大小
 CString m_strFileName;//文件名
 CString m_strFilePath;//文件路径
// Dialog Data
 //{{AFX_DATA(CClient_FTPDlg)
 enum { IDD = IDD_CLIENT_FTP_DIALOG };
 CProgressCtrl m_Progress;
 CListCtrl m_ListFile;
 CIPAddressCtrl m_IPAddr;
 CLabel m_LabProgress;
 //}}AFX_DATA

 // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(CClient_FTPDlg)
 protected:
 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
 //}}AFX_VIRTUAL

// Implementation
protected:
 HICON m_hIcon;

 // Generated message map functions
 //{{AFX_MSG(CClient_FTPDlg)
 virtual BOOL OnInitDialog();
 afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
 afx_msg void OnPaint();
 afx_msg HCURSOR OnQueryDragIcon();
 afx_msg BOOL OnEraseBkgnd(CDC* pDC);
 afx_msg void OnBtnScan();
 afx_msg void OnBtnUpdate();
 afx_msg void OnDestroy();
 afx_msg void OnDblclkListFile(NMHDR* pNMHDR, LRESULT* pResult);
 //}}AFX_MSG

 afx_msg LRESULT OnFileDownload(WPARAM wp, LPARAM lp);
 afx_msg LRESULT OnFileUpdate(WPARAM wp, LPARAM lp);
 afx_msg LRESULT OnFileList(WPARAM wp, LPARAM lp);
 afx_msg LRESULT OnConnectError(WPARAM wp, LPARAM lp);

 DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_CLIENT_FTPDLG_H__E7F99F34_0BD2_4B11_8FF7_D958887D2368__INCLUDED_)

//对话框 cpp 文件

// Client_FTPDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Client_FTP.h"
#include "Client_FTPDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
 CAboutDlg();

// Dialog Data
 //{{AFX_DATA(CAboutDlg)
 enum { IDD = IDD_ABOUTBOX };
 //}}AFX_DATA

 // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(CAboutDlg)
 protected:
 virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
 //}}AFX_VIRTUAL

// Implementation
protected:
 //{{AFX_MSG(CAboutDlg)
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
 //{{AFX_DATA_INIT(CAboutDlg)
 //}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
 //{{AFX_DATA_MAP(CAboutDlg)
 //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
 //{{AFX_MSG_MAP(CAboutDlg)
  // No message handlers
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CClient_FTPDlg dialog

CClient_FTPDlg::CClient_FTPDlg(CWnd* pParent /*=NULL*/)
 : CDialog(CClient_FTPDlg::IDD, pParent)
{
 //{{AFX_DATA_INIT(CClient_FTPDlg)
 //}}AFX_DATA_INIT
 // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

 m_bConnected = FALSE;
 m_strFileName = _T("");
 m_lFileSize = 0;

}

void CClient_FTPDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
 //{{AFX_DATA_MAP(CClient_FTPDlg)
 DDX_Control(pDX, IDC_PROGRESS1, m_Progress);
 DDX_Control(pDX, IDC_LIST_FILE, m_ListFile);
 DDX_Control(pDX, IDC_IPADDRESS1, m_IPAddr);
 DDX_Control(pDX, IDC_STATIC_PROGRESS, m_LabProgress);
 //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CClient_FTPDlg, CDialog)
 //{{AFX_MSG_MAP(CClient_FTPDlg)
 ON_WM_SYSCOMMAND()
 ON_WM_PAINT()
 ON_WM_QUERYDRAGICON()
 ON_WM_ERASEBKGND()
 ON_BN_CLICKED(IDC_BTN_SCAN, OnBtnScan)
 ON_BN_CLICKED(IDC_BTN_UPDATE, OnBtnUpdate)
 ON_WM_DESTROY()
 ON_NOTIFY(NM_DBLCLK, IDC_LIST_FILE, OnDblclkListFile)
 //}}AFX_MSG_MAP
 ON_MESSAGE(WM_FILELIST, OnFileList)
 ON_MESSAGE(WM_FILEUPDATE, OnFileUpdate)
 ON_MESSAGE(WM_FILEDOWNLOAD, OnFileDownload)
 ON_MESSAGE(WM_CONNECTERROR, OnConnectError)
END_MESSAGE_MAP()

/
// CClient_FTPDlg message handlers

BOOL CClient_FTPDlg::OnInitDialog()
{
 CDialog::OnInitDialog();

 // Add "About..." menu item to system menu.

 // IDM_ABOUTBOX must be in the system command range.
 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 ASSERT(IDM_ABOUTBOX < 0xF000);

 CMenu* pSysMenu = GetSystemMenu(FALSE);
 if (pSysMenu != NULL)
 {
  CString strAboutMenu;
  strAboutMenu.LoadString(IDS_ABOUTBOX);
  if (!strAboutMenu.IsEmpty())
  {
   pSysMenu->AppendMenu(MF_SEPARATOR);
   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  }
 }

 // Set the icon for this dialog.  The framework does this automatically
 //  when the application's main window is not a dialog
 SetIcon(m_hIcon, TRUE);   // Set big icon
 SetIcon(m_hIcon, FALSE);  // Set small icon

 m_LabProgress.SetFontSize(20);
 m_LabProgress.SetBkColor(BACKCOLOR);
 m_Progress.SetRange(0, 100);
 m_Progress.SetPos(0);
 m_LabProgress.SetText(_T("0%"));

 m_IPAddr.SetAddress(127, 0, 0, 1);
 SetDlgItemInt(IDC_EDIT_PORT, 7000);
 InitListColumn();

 m_pFtpClient = new CFtp_Client();
 
 // TODO: Add extra initialization here
 
 return TRUE;  // return TRUE  unless you set the focus to a control
}

void CClient_FTPDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
 if ((nID & 0xFFF0) == IDM_ABOUTBOX)
 {
  CAboutDlg dlgAbout;
  dlgAbout.DoModal();
 }
 else
 {
  CDialog::OnSysCommand(nID, lParam);
 }
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CClient_FTPDlg::OnPaint()
{
 if (IsIconic())
 {
  CPaintDC dc(this); // device context for painting

  SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

  // Center icon in client rectangle
  int cxIcon = GetSystemMetrics(SM_CXICON);
  int cyIcon = GetSystemMetrics(SM_CYICON);
  CRect rect;
  GetClientRect(&rect);
  int x = (rect.Width() - cxIcon + 1) / 2;
  int y = (rect.Height() - cyIcon + 1) / 2;

  // Draw the icon
  dc.DrawIcon(x, y, m_hIcon);
 }
 else
 {
  CDialog::OnPaint();
 }
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CClient_FTPDlg::OnQueryDragIcon()
{
 return (HCURSOR) m_hIcon;
}

BOOL CClient_FTPDlg::OnEraseBkgnd(CDC* pDC)
{
 // TODO: Add your message handler code here and/or call default
 //更改背景颜色
 CRect rect;
 GetClientRect(&rect);
 pDC->FillSolidRect(&rect, BACKCOLOR);
 return TRUE;
 // return CDialog::OnEraseBkgnd(pDC);
}

void CClient_FTPDlg::OnBtnScan()
{
 // TODO: Add your control notification handler code here
 //文件选择
 CFileDialog fileDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "All Files(*.*)|*.*||", this);
 if(fileDlg.DoModal() == IDOK)
 {
  //获取文件路径
  CString strPathName = fileDlg.GetPathName();
  CFile file;
  BOOL bOpen = file.Open(strPathName, CFile::modeRead|CFile::shareDenyNone, NULL);
  if(!bOpen)
  {
   MessageBox("打开失败,请确认路径再重试!");
   return;
  }

  m_lFileSize = file.GetLength();
  m_strFilePath = strPathName;
  m_strFileName = fileDlg.GetFileName();
  file.Close();

  SetDlgItemText(IDC_EDIT_PATH, strPathName);

  //获取服务器IP和端口
  BYTE btye1, btye2, btye3, btye4;
  m_IPAddr.GetAddress(btye1, btye2, btye3, btye4);
  char sIP[15];
  sprintf(sIP, "%d.%d.%d.%d", btye1, btye2, btye3, btye4);//显示IP地址
  int nPort = GetDlgItemInt(IDC_EDIT_PORT);
  CString strIP(sIP);
  if (strIP.IsEmpty())
  {
   AfxMessageBox(_T("请输入服务器IP地址!"));
   return;
  }
  if (nPort<0)
  {
   AfxMessageBox(_T("请输入服务器端口!"));
   return;
  }
  m_pFtpClient->InitParam(this, sIP, nPort);

  //发送文件信息到服务器
   MSGPARAM msgParam;
   msgParam.msgFile.iCommand = FILELIST;
   msgParam.msgFile.lFileLength = m_lFileSize;
   msgParam.msgFile.lFileOffset = 0;
   strcpy(msgParam.msgFile.sFilePath, strPathName);
   m_pFtpClient->SendRequest(msgParam);
 }
}

void CClient_FTPDlg::OnBtnUpdate()
{
 // TODO: Add your control notification handler code here
 CString strPathName;
 GetDlgItemText(IDC_EDIT_PATH, strPathName);
 //是否有要上传的文件
 if (strPathName.IsEmpty())
 {
  AfxMessageBox(_T("请先选择要上传的文件!"));
  return;
 }
 
 //上传文件
 MSGPARAM msgParam;
 msgParam.msgFile.iCommand = FILEUPDATE;
 msgParam.msgFile.lFileLength = m_lFileSize;
 msgParam.msgFile.lFileOffset = 0;
 strcpy(msgParam.msgFile.sFilePath, strPathName);
 m_pFtpClient->SendRequest(msgParam);
}

void CClient_FTPDlg::InitListColumn()
{
 int iWidth = 50;
 m_ListFile.InsertColumn(0, "文件名", LVCFMT_LEFT, 3*iWidth, -1);
 m_ListFile.InsertColumn(1, "文件大小", LVCFMT_LEFT, 2*iWidth, -1);
 m_ListFile.InsertColumn(2, "下载速度", LVCFMT_LEFT, 2*iWidth, -1);
 m_ListFile.InsertColumn(3, "下载状态", LVCFMT_LEFT, 2*iWidth, -1);
 m_ListFile.InsertColumn(4, "下载时间", LVCFMT_LEFT, 2*iWidth, -1);
 m_ListFile.InsertColumn(5, "文件保存路径", LVCFMT_LEFT, 5*iWidth, -1);
 m_ListFile.InsertColumn(6, "时间标记", LVCFMT_LEFT, 2*iWidth, -1);
 //插入列:左对齐,无子列
 m_ListFile.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
}

void CClient_FTPDlg::OnDestroy()
{
 CDialog::OnDestroy();
 
 // TODO: Add your message handler code here
 if(m_pFtpClient != NULL)
 {
  m_pFtpClient->StopThread();
  delete m_pFtpClient;
 }
}

LRESULT CClient_FTPDlg::OnFileList(WPARAM wp, LPARAM lp)
{
 SOCKET sock = (SOCKET)wp;
 MSGFILELIST msgFileList;
 msgFileList.lFileLength = m_lFileSize;
 strcpy(msgFileList.sFilePath, m_strFilePath.GetBuffer(0));
 //发送文件信息
 int iSendCnt = send(sock, (char*)&msgFileList, sizeof(msgFileList), 0);

 return 0;
}

LRESULT CClient_FTPDlg::OnFileUpdate(WPARAM wp, LPARAM lp)
{
 MSGFILESTATUS* pmsg = (MSGFILESTATUS*)wp;
 int nPos = int((float)pmsg->lFileOffset/m_lFileSize*100);
 m_Progress.SetPos(nPos);
 CString strStatus;
 strStatus.Format("%d%%", nPos);
 m_LabProgress.SetText(strStatus);
 if (nPos<100)
  return 0;

 CString strFileSize;//显示文件大小
 strFileSize.Format("%0.2fk", (float)m_lFileSize/1024);

 int iItem = m_ListFile.GetItemCount();//获取文件列表元素个数
 LV_ITEM lvi;//结构体ListView Item,指定或接收属性
    
 lvi.mask = LVIF_TEXT|LVIF_PARAM;
 lvi.iItem = iItem;
 lvi.iSubItem = 0;
 lvi.lParam = m_lFileSize;
 lvi.pszText = m_strFileName.GetBuffer(0);//返回CString中指向字符串的指针
 m_ListFile.InsertItem(&lvi);//插入列表
 m_ListFile.SetItemText(iItem, 1, strFileSize.GetBuffer(0));
 m_ListFile.SetItemText(iItem, 5, m_strFilePath.GetBuffer(0));
    
 return 0;
}

LRESULT CClient_FTPDlg::OnFileDownload(WPARAM wp, LPARAM lp)
{
 MSGFILESTATUS* pmsg = (MSGFILESTATUS*)wp;
 CString strPath, strName;
 strPath.Format("%s", pmsg->sFilePath);
 int iPos = strPath.ReverseFind('\\');
 strName = strPath.Right(strPath.GetLength() - iPos - 1);
 int iTotal = m_ListFile.GetItemCount();
 int iSel = 0;
 for(; iSel<iTotal; iSel++)
 {
  CString strListPath;
  strListPath = m_ListFile.GetItemText(iSel, 0);
  if(strName.Compare(strListPath) == 0)//路径相同
   break;
 }
 if(iSel == iTotal)
  return 1;

 long lFileLength = m_ListFile.GetItemData(iSel);
 CString strStatus;
 strStatus.Format("%0.2f%%", (float)pmsg->lFileOffset/lFileLength*100);
 //显示状态 %,精确到小数点后两位
 m_ListFile.SetItemText(iTotal-1, 3, strStatus.GetBuffer(0));
 
 //显示时间
 DWORD dwNowTick, dwStartTick;//毫秒
 dwNowTick = GetTickCount();
 sscanf(m_ListFile.GetItemText(iSel, 6), "%u", &dwStartTick);
 
 long iEllapsed = (dwNowTick-dwStartTick);//间隔:秒
 strStatus.Format("%dms", iEllapsed);
 m_ListFile.SetItemText(iSel, 4, strStatus.GetBuffer(0));
 
 //显示速度
 if(iEllapsed > 0)
 {
  strStatus.Format("%dk/s", (pmsg->lFileOffset/1024/iEllapsed)*1000);
  m_ListFile.SetItemText(iSel, 2, strStatus.GetBuffer(0));
 }

 return 0;
}

LRESULT CClient_FTPDlg::OnConnectError(WPARAM wp, LPARAM lp)
{
 AfxMessageBox(_T("服务器连接失败!"));
 return 0;
}

void CClient_FTPDlg::OnDblclkListFile(NMHDR* pNMHDR, LRESULT* pResult)
{
 // TODO: Add your control notification handler code here
 NMLISTVIEW* pListView = (NMLISTVIEW*)pNMHDR;//结构体,ListView的通知信息
 int iSel = pListView->iItem;
 if(iSel == -1)
  return;
 
 CString strFileName = m_ListFile.GetItemText(iSel, 0);
 CFileDialog dlg(FALSE, NULL, strFileName.GetBuffer(0), OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "All Files(*.*)|*.*||", this);
 //打开一个保存对话框,隐藏readonly||覆盖确认
 if(dlg.DoModal() != IDOK)
  return;
 
 CString strClientPath = dlg.GetPathName();
 //得到客户端保存路径
 CFile file;
 BOOL bOpen = file.Open(strClientPath, CFile::modeCreate|CFile::modeWrite, NULL);
 if(!bOpen)
 {
  MessageBox("文件创建或打开失败,请确认路径再重试!");
  return;
 }
 file.Close();

 MSGPARAM msgParam;
 msgParam.msgFile.iCommand = FILEDOWNLOAD;
 msgParam.msgFile.lFileLength = m_ListFile.GetItemData(iSel);
 msgParam.msgFile.lFileOffset = 0;
 strcpy(msgParam.msgFile.sFilePath, strClientPath);
 //子项目,第6列
 
 DWORD dwStartTick = GetTickCount();
 char sStartTick[20];
 sprintf(sStartTick, "%u", dwStartTick);
 m_ListFile.SetItemText(iSel, 6, sStartTick);
 
 m_pFtpClient->SendRequest(msgParam);//调用请求线程

 *pResult = 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值