1. 程式人生 > >FTP檔案上傳demo

FTP檔案上傳demo

該demo主要是封裝了MS的Wininet.dll,方便FTP檔案上傳,
解決了在XP系統下面InternetConnect()介面在FTP伺服器不可用,連線超時嚴重,且不可控的問題。
該demo在WIN7 64 和XP 32 自測通過。
完整工程原始碼下載地址:

------------------------------------------------------------------------------------------

主要程式碼如下:
ftp.h

#pragma once
#pragma warning(disable:4995)

#include <strsafe.h>
#include <process.h>
#include <Wininet.h>
#pragma comment(lib, "Wininet.lib")

#include <vector>
#include <string>
using std::vector;
using std::string;
using std::wstring;

#ifdef _UNICODE
#define tstring wstring
#else
#define tstring string
#endif

// FTP配置引數
typedef struct tagFtpParam
{
	int iFtpEnable;             // 1開啟FTP上傳,0是關閉FTP上傳
	TCHAR szFtpServerIp[32];    // FTP伺服器IP
	TCHAR szFtpUser[20];        // FTP登陸賬號
	TCHAR szFtpPass[30];        // FTP登陸密碼
	int iFtpPort;               // FTP服務埠, 預設為21
	int iFtpIsPassive;          // 1表示FTP為被動模式,0表示FTP為主動模式
	TCHAR szFtpUploadDir[30];   // FTP上傳目錄,如 /test

	tagFtpParam()
	{
		iFtpEnable = 0;
		ZeroMemory(szFtpServerIp, sizeof(szFtpServerIp));
		ZeroMemory(szFtpUser, sizeof(szFtpUser));
		ZeroMemory(szFtpPass, sizeof(szFtpPass));
		iFtpPort = 21;
		iFtpIsPassive = 1;
		ZeroMemory(szFtpUploadDir, sizeof(szFtpUploadDir));
		StringCbCopy(szFtpUploadDir, sizeof(szFtpUploadDir), _T("/test"));
	}

}FtpParam;


class CFtp
{
public:

	CFtp(void);

	~CFtp(void);


	/**
	@name    UploadDiskFile
	@brief	 往FTP上傳磁碟檔案
	@param[in]        LPCTSTR pszFilePath,	磁碟檔案路徑
	@param[in]        LPCTSTR pszUploadDir,	上傳到的FTP目錄,以斜槓/開頭,如 /test
	@return           成功true,失敗false
	*/
	bool UploadDiskFile(LPCTSTR pszFilePath, LPCTSTR pszUploadDir);



	/**
	@name    UploadMemoryFile
	@brief	 往FTP上傳記憶體檔案
	@param[in]        PBYTE pbFile,			記憶體檔案緩衝區指標
	@param[in]        int iFileLen,			記憶體檔案長度
	@param[in]        LPCTSTR pszFileName,	儲存檔名稱
	@param[in]        LPCTSTR pszUploadDir, 上傳到的FTP目錄,以斜槓開頭,如/test
	@return           bool
	*/
	bool UploadMemoryFile(PBYTE pbFile, int iFileLen, LPCTSTR pszFileName, LPCTSTR pszUploadDir);

	/**
	@name    IsFileExists
	@brief   判斷檔案是否存在 
	@param[in]:        LPCTSTR pszFilePath  檔案路徑
	@return            檔案存在返回true, 否則返回false
	*/
	bool IsFileExists(LPCTSTR pszFilePath);


public:

	FtpParam m_ftpParam;	// ftp配置引數

private:

	/**
	@name    ConnFtpServer
	@brief	 連線FTP伺服器
	@param[in]        void
	@return   成功true,失敗false
	*/
	bool ConnFtpServer(void);

	// 連線FTP執行緒代理
	static unsigned int _stdcall ThreadConnFtpProxy(PVOID pParam)
	{
		CFtp *pThis = (CFtp*)pParam;
		if (pThis != NULL)
		{
			pThis->ThreadConnFtp();
		}
		return 0;
	}


	/**
	@name    ThreadConnFtp
	@brief	 連線FTP執行緒
	@param[in]        void
	@return           bool
	*/
	bool ThreadConnFtp(void);

private:
	HINTERNET m_hInetOpen;	// 網路開啟控制代碼
	HINTERNET m_hInetConn;	// 網路連線控制代碼
	HANDLE m_hConnThread;	// 連線執行緒控制代碼
};


ftp.cpp
#include "StdAfx.h"
#include "Ftp.h"

CFtp::CFtp(void)
{
	m_hInetOpen = NULL;
	m_hInetConn = NULL;
	m_hConnThread = NULL;
}

CFtp::~CFtp(void)
{
	if (m_hInetOpen != NULL)
	{
		InternetCloseHandle(m_hInetOpen);
		m_hInetOpen = NULL;
	}
	if (m_hInetConn != NULL)
	{
		InternetCloseHandle(m_hInetConn);
		m_hInetConn = NULL;
	}

	if (m_hConnThread != NULL)
	{
		WaitForSingleObject (m_hConnThread, 1000*30);
		CloseHandle(m_hConnThread);
		m_hConnThread = NULL;
	}
}

/**
	@name    ConnFtpServer
	@brief	 連線FTP伺服器
	@param[in]        void
	@return   成功true,失敗false
	*/
bool CFtp::ConnFtpServer(void)
{

	WaitForSingleObject(m_hConnThread, 1000*60);
	m_hConnThread = (HANDLE)_beginthreadex(NULL, 0, ThreadConnFtpProxy, this, 0, NULL);
	DWORD   dwTimeout = 1000*3;	// 連線FTP超時時間
	if (WaitForSingleObject (m_hConnThread, dwTimeout ) == WAIT_TIMEOUT)
	{
		TerminateThread(m_hConnThread, -1);
		if (m_hConnThread != NULL)
		{
			CloseHandle(m_hConnThread);
			m_hConnThread = NULL;
		}
		return false;
	}

	if (m_hConnThread != NULL)
	{
		CloseHandle(m_hConnThread);
		m_hConnThread = NULL;
	}
	return true;
}

/**
	@name    UploadDiskFile
	@brief	 往FTP上傳磁碟檔案
	@param[in]        LPCTSTR pszFilePath,	磁碟檔案路徑
	@param[in]        LPCTSTR pszUploadDir,	上傳到的FTP目錄,以斜槓/開頭,如 /test
	@return           成功true,失敗false
	*/
bool CFtp::UploadDiskFile(LPCTSTR pszFilePath, LPCTSTR pszUploadDir)
{
	if (pszFilePath == NULL || m_ftpParam.iFtpEnable == 0)
	{
		return false;
	}
	if (!IsFileExists(pszFilePath))
	{
		return false;
	}
	if (!ConnFtpServer())
	{
		return false;
	}

	// 解析上傳目錄
	tstring strUploadDir;
	if (_tcslen(pszUploadDir) > 0)
	{
		strUploadDir = pszUploadDir;
	}
	else    
	{
		strUploadDir = m_ftpParam.szFtpUploadDir;    // 預設上傳目錄
	}
	if (strUploadDir.size() <= 0)
	{
		strUploadDir = _T("/result/");
	}
	strUploadDir[0] = _T('/');		// 確保以斜槓/開頭
	if (strUploadDir[strUploadDir.size() - 1] != _T('/'))
	{
		strUploadDir += _T('/');	// 確保以斜槓/結尾
	}
	
	
	// 確保上傳目錄存在 strUploadDir = /test
	tstring strCurDir = _T("/");
	FtpSetCurrentDirectory(m_hInetConn, strCurDir.c_str());
	tstring strTmpDir = strUploadDir;
	bool bRet = true;
	while(strTmpDir.find(_T('/')) != tstring::npos && bRet)
	{
		size_t iStart = strTmpDir.find(_T('/'));
		strTmpDir.erase(iStart, 1);
		size_t iEnd = strTmpDir.find(_T('/'));
		tstring strDir = strTmpDir.substr(iStart, iEnd - iStart);
		bRet = FtpCreateDirectory(m_hInetConn, strDir.c_str()) > 0 ? true : false;
		strCurDir += strDir;
		strCurDir += _T('/');
		FtpSetCurrentDirectory(m_hInetConn, strCurDir.c_str());
		if (iEnd == strTmpDir.size() - 1)
		{
			break;
		}
	}
	FtpSetCurrentDirectory(m_hInetConn, strUploadDir.c_str());

	// 解析上傳磁碟檔名稱,如 D:\test.txt
	tstring strDiskFilePath = pszFilePath;
	tstring strDiskFileName;
	size_t iIndex = strDiskFilePath.rfind('\\');
	if (iIndex != tstring::npos && iIndex >= 0)
	{
		strDiskFileName = strDiskFilePath.substr(iIndex+1, strDiskFilePath.size() - 1);
	}

	// 上傳磁碟檔案
	tstring strTmpFile = strUploadDir;
	strTmpFile += strDiskFileName;
	bRet = FtpPutFile(m_hInetConn, pszFilePath, strTmpFile.c_str(), FTP_TRANSFER_TYPE_BINARY, NULL) > 0 ? true : false;

	// 獲取錯誤資訊
	if (!bRet)
	{
		DWORD iErrorCode = GetLastError();
		TCHAR szErr[1024] = {0};
		DWORD dwLen = 1024;
		InternetGetLastResponseInfo(&iErrorCode, szErr, &dwLen);
		OutputDebugString(szErr);
	}

	return bRet;
}


/**
	@name    UploadMemoryFile
	@brief	 往FTP上傳記憶體檔案
	@param[in]        PBYTE pbFile,			記憶體檔案緩衝區指標
	@param[in]        int iFileLen,			記憶體檔案長度
	@param[in]        LPCTSTR pszFileName,	儲存檔名稱
	@param[in]        LPCTSTR pszUploadDir, 上傳到的FTP目錄,以斜槓開頭,如/test
	@return           bool
	*/
bool CFtp::UploadMemoryFile(PBYTE pbFile, int iFileLen, LPCTSTR pszFileName, LPCTSTR pszUploadDir)
{
	if (pbFile == NULL || iFileLen < 1 || m_ftpParam.iFtpEnable == 0)
	{
		return false;
	}
	if (pszFileName == NULL)
	{
		return false;
	}
	if (!ConnFtpServer())
	{
		return false;
	}

	// 解析上傳目錄
	tstring strUploadDir;
	if (_tcslen(pszUploadDir) > 0)
	{
		strUploadDir = pszUploadDir;
	}
	else    
	{
		strUploadDir = m_ftpParam.szFtpUploadDir;    // 預設上傳目錄
	}
	if (strUploadDir.size() <= 0)
	{
		strUploadDir = _T("/result/");
	}
	strUploadDir[0] = _T('/');					        // 確保以斜槓/開頭
	if (strUploadDir[strUploadDir.size() - 1] != _T('/'))
	{
		strUploadDir += _T('/');	// 確保以斜槓/結尾
	}

	// 確保上傳目錄存在 strUploadDir = /test 
	tstring strCurDir = _T("/");
	FtpSetCurrentDirectory(m_hInetConn, strCurDir.c_str());
	tstring strTmpDir = strUploadDir;
	bool bRet = true;
	while(strTmpDir.find(_T('/')) != tstring::npos && bRet)
	{
		size_t iStart = strTmpDir.find(_T('/'));
		strTmpDir.erase(iStart, 1);
		size_t iEnd = strTmpDir.find(_T('/'));
		tstring strDir = strTmpDir.substr(iStart, iEnd - iStart);
		bRet = FtpCreateDirectory(m_hInetConn, strDir.c_str()) > 0 ? true : false;
		strCurDir += strDir;
		strCurDir += _T('/');
		FtpSetCurrentDirectory(m_hInetConn, strCurDir.c_str());
		if (iEnd == strTmpDir.size() - 1)
		{
			break;
		}
	}
	FtpSetCurrentDirectory(m_hInetConn, strUploadDir.c_str());

	// 解析上傳記憶體檔名稱
	tstring strMemoryFileName = pszFileName;

	// 上傳記憶體檔案
	HINTERNET hFtpFile = NULL;
	tstring strTmpFile = strUploadDir;
	strTmpFile += strMemoryFileName;
	hFtpFile = FtpOpenFile(m_hInetConn, strTmpFile.c_str(), GENERIC_WRITE, INTERNET_FLAG_TRANSFER_BINARY, NULL);
	if (hFtpFile != NULL)
	{
		DWORD dwWrite = 0;
		bRet = InternetWriteFile(hFtpFile, pbFile, iFileLen, &dwWrite) > 0 ? true : false;
	}

	// 獲取錯誤資訊
	if (!bRet)
	{
		DWORD iErrorCode = GetLastError();
		TCHAR szErr[1024] = {0};
		DWORD dwLen = 1024;
		InternetGetLastResponseInfo(&iErrorCode, szErr, &dwLen);
		OutputDebugString(szErr);
	}

	// 釋放記憶體
	if (hFtpFile != NULL)
	{
		InternetCloseHandle(hFtpFile);
		hFtpFile = NULL;
	}

	return bRet;
}


/**
	@name    IsFileExists
	@brief   判斷檔案是否存在 
	@param[in]:        LPCTSTR pszFilePath  檔案路徑
	@return            檔案存在返回true, 否則返回false
	*/
bool CFtp::IsFileExists(LPCTSTR pszFilePath)
{
	if (pszFilePath == NULL)
	{
		return false;
	}
	HANDLE hRet = CreateFile(pszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	bool bRet = false;
	if (hRet != INVALID_HANDLE_VALUE )   // 檔案存在 
	{
		bRet = true;
	}
	CloseHandle(hRet);
	return bRet;
}

/**
	@name    ThreadConnFtp
	@brief	 連線FTP執行緒
	@param[in]        void
	@return           bool
	*/
bool CFtp::ThreadConnFtp(void)
{
	if (m_hInetOpen != NULL)
	{
		InternetCloseHandle(m_hInetOpen);
		m_hInetOpen = NULL;
	}
	if (m_hInetConn != NULL)
	{
		InternetCloseHandle(m_hInetConn);
		m_hInetConn = NULL;
	}

	// 連線FTP 伺服器
	//HINTERNET hInetOpen = InternetOpen(_T("CN"), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC);  // 非同步
	m_hInetOpen = InternetOpen(_T("CN"), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);  // 同步 
	if (m_hInetOpen == NULL)
	{
		return false;
	}

	DWORD dwFlags = 0;
	if(m_ftpParam.iFtpIsPassive == 1)
	{
		dwFlags = INTERNET_FLAG_PASSIVE;
	}
	//DWORD dwTimeOut = 1000*3;	// 超時值,經測試在WIN7有效,在XP無效,現已改成由執行緒控制
	//InternetSetOption(m_hInetOpen, INTERNET_OPTION_CONNECT_TIMEOUT, &dwTimeOut, sizeof(dwTimeOut));
	m_hInetConn = InternetConnect(m_hInetOpen, 
									m_ftpParam.szFtpServerIp, 
									m_ftpParam.iFtpPort,
									m_ftpParam.szFtpUser,
									m_ftpParam.szFtpPass,
									INTERNET_SERVICE_FTP,
									dwFlags,
									NULL);

	if (m_hInetConn == NULL)
	{
		return false;
	}
	return true;
}


相關推薦

FTP檔案demo

該demo主要是封裝了MS的Wininet.dll,方便FTP檔案上傳, 解決了在XP系統下面InternetConnect()介面在FTP伺服器不可用,連線超時嚴重,且不可控的問題。 該demo在WIN7 64 和XP 32 自測通過。 完整工程原始碼下載地址: --

Android關於FTP檔案和下載功能詳解

Android關於FTP檔案上傳和下載功能詳解  更新時間:2017年09月21日 11:41:14   作者:一諾的祕密花園    我要評論 這篇文章主要為大家詳細介紹了Android關於FTP檔案上傳和下載功能,具有一定的參考價值,感興趣

webuploader如何使用,webuploader檔案demo,使用webuploader檔案

webuploader是百度開發的一個js上傳檔案的元件, 你可以免費使用它, 實現上傳檔案,圖片,壓縮包等。 由於webuploader官方文件都是講述前端,js怎麼使用, 很少提及到伺服器端的程式

【高效開發外掛】09 FTPUtil FTP 檔案工具類

package com.yuu.mall.util; import org.apache.commons.net.ftp.FTPClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory;

Java 實現ftp 檔案、下載和刪除

本文利用apache ftp工具實現檔案的上傳下載和刪除。具體如下: 1、下載相應的jar包      commons-net-1.4.1.jar 2、實現程式碼如下: public class FtpUtils { //ftp伺服器地址

寶塔-PHP-伺服器-資料庫-FTP-檔案 問題集

簡介:    今天分享一下自己寫的筆記,最近部署伺服器所遇到的各種問題,比較典型的問題都寫在了筆記裡面,現在我把筆記分享給出來,希望可以給大家一點幫助~ 問題目錄: 1.寶塔設定 伺服器 本地資料庫、RDS雲資料庫 連線不上 2.寶塔設定 伺服器 FTP無法連線

centos6.5 ftp檔案遇到的問題彙總

1、ftp 192.168.1.* -bash: ftp: command not found 解決方案:ftp命令沒有安裝  # yum install ftp 2、ftp: connect: 拒絕連線     解決方案:     (1

java 中 FtpClient 實現 FTP 檔案、下載

package ftp; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWrit

使用Socket 完成HTTP post方式的文字及檔案 demo

   程式碼結構: Android端 Web端 最終結果    該demo具有很強的通用性,而且程式碼的複用性極高,基本上以後不需要再為檔案上傳花費太多時間,拿過去直接可以用。    剛開始從

SWFUpload實現多檔案DEMO

         引言:最近專案中需要用到多檔案上傳,在網上找了很多資料,最開始使用的是uploadify這個外掛,在使用的過程中各種問題,什麼Flash版本的問題,瀏覽器相容性的問題總之是一大堆,最後在眾多問題下,無奈只好放棄了。最後選擇了SWFUpload,在網上下載了

shutil模組和幾種檔案Demo

一、shutil模組 1、介紹 shutil模組是對os中檔案操作的補充。--移動 複製 打包 壓縮 解壓   2、基本使用 1. shutil.copyfileobj(檔案1, 檔案2, 長度) 將檔案1的資料覆蓋copy給檔案2,可以copy指定大小的內容 檔案1和2都是檔案

用ASP.NET的FileUpload控制元件實現帶對話方塊的FTP檔案功能

      最近不得已開始做網頁,一個ASP.NET的專案,需要實現FTP上傳功能,於是上網廣搜程式碼,發現FTP上傳的程式碼到處都是,隨手拈來,可是一般來說客戶端上傳檔案都需要一個檔案選擇對話方塊,正好自帶的FileUpload控制元件能夠實現。但是網上搜到FileUpl

java ftp檔案下載刪除

package ftp; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStre

十八.Python模擬FTP檔案

Python 模擬FTP斷點續傳併發伺服器   #配置檔案 #伺服器配置檔案 [server_config] ip=127.0.0.1 port=8006 buffersize=1024 encoding=utf-8 #伺服器使用者資料 

FTP檔案

public class FTPUtil { private static final Logger logger = LoggerFactory.getLogger(FTPUtil.class); private static String ftpIp = PropertiesUtil

java/struts/Servlet檔案下載與ftp檔案下載

String s1=transUrl; // transUrl是前臺接受的引數,get接受的引數tomcat一律使用iso-8859-1編碼 transUrl=new String(transUrl.getBytes("ISO-8859-1"),"utf-8");//程式中要使用的檔名,必須轉換為gbk

java 檔案demo

每次寫程式碼都要查詢,所以就放這裡面備份了 基本pom引用: <dependency> <groupId>org.apache.httpcomponents</groupId&

Shell FTP檔案下載

1.上傳檔案到ftp 建立一個shell檔案:touch upload.sh 修改為可執行檔案:chmod +x upload.sh 編輯:vim upload.sh,指令碼內容如下 cd /user/directory/target export putfile=y

使用FileZilla連線Linux伺服器正常連線,但是無法圖片[FTP檔案]

使用FileZilla進行連線伺服器,不能上傳圖片的解決方式:     1.將要上傳到伺服器上的資料夾的許可權改為777,如chmod -R 777 /var/images     2.開啟vsftp

基於spring boot ftp檔案

對ftp檔案上傳將行封裝,實現連線的單例模式,完成執行緒安全的改進,ftp檔案上傳下載失敗的重試。application.yml配置檔案ftp:    ip: 127.0.0.1    port: 21    username: admin    password: admi