該代碼主要實現,指定ftp服務地址,遍歷下載該地址下所有文件(含子文件夾下文件),並提供進度條顯示;另外附帶有通過http地址方式獲取服務器文件的簡單實例
廢話不多說,直接上代碼:
1、FTPHelper類
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
namespace FileBackup.FTP
{
/// <summary>
/// FTP服務器文件處理
/// </summary>
public class FTPHelper
{
private string _path; //ftp服務地址
private bool _isAuth; //是否需要身份驗證
private string _userName; //用戶名
private string _password; //密碼
public FTPHelper(string path, bool isAuth, string userName, string password)
{
_path = path;
_isAuth = isAuth;
_userName = userName;
_password = password;
}
/// <summary>
/// 獲取ftp路徑地址下文件/文件夾
/// </summary>
/// <param name="relativePath">相對於ftp服務地址的路徑(相對路徑);不傳參則代表獲取ftp服務地址根目錄</param>
/// <param name="isFloder">1、不傳參:獲取文件和文件夾;2、true:僅獲取文件夾;3、false:僅獲取文件</param>
/// <returns></returns>
public List<string> GetFileList(string relativePath = null, bool? isFloder = null)
{
List<string> result = new List<string>();
FtpWebRequest request;
try
{
string path = _path;
if (!string.IsNullOrEmpty(relativePath))
{
path += relativePath;
}
request = (FtpWebRequest)FtpWebRequest.Create(new Uri(path));
request.UseBinary = true; //指定文件以二進制方式傳輸
//是否需要身份驗證
if (!_isAuth)
{
request.Credentials = new NetworkCredential();
}
else
{
//設置用戶名和密碼
request.Credentials = new NetworkCredential(_userName, _password);
}
//設置ftp的命令
if (isFloder.HasValue)
{
//僅獲取列表
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
}
else
{
//獲取詳情(僅獲取詳情時可以區分文件和文件夾)
request.Method = WebRequestMethods.Ftp.ListDirectory;
}
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string line = reader.ReadLine();
while (line != null)
{
//是否區分文件夾/文件讀取文件;若不區分,文件夾及文件會一起讀取
if (isFloder.HasValue)
{
//僅讀取文件夾
if ((bool)isFloder)
{
if (line.Contains("<DIR>"))
{
result.Add(line.Substring(line.LastIndexOf("<DIR>") + 5).Trim());
}
}
else
{
//讀取文件夾下文件
if (!line.Contains("<DIR>"))
{
result.Add(line.Substring(39).Trim());
}
}
}
else
{
result.Add(line.Trim());
}
//讀取下一行
line = reader.ReadLine();
}
reader.Close();
response.Close();
return result;
}
catch (Exception ex)
{
Console.WriteLine("get the files/folders from the ftp:" + ex.Message);
}
return null;
}
/// <summary>
/// 從FTP服務器下載文件,指定本地路徑和本地文件名(支持斷點下載)
/// </summary>
/// <param name="relativePath">遠程文件名</param>
/// <param name="localFileName">保存本地的文件名(包含路徑)</param>
/// <param name="size">已下載文件流大小</param>
/// <param name="updateProgress">報告進度的處理(第一個參數:總大小,第二個參數:當前進度)</param>
/// <returns>是否下載成功</returns>
public bool FtpBrokenDownload(string relativePath, string localFileName, long size, Action<string, int, int, int> updateProgress = null, int? index = null)
{
FtpWebRequest reqFTP, ftpsize;
Stream ftpStream = null;
FtpWebResponse response = null;
FileStream outputStream = null;
try
{
string path = _path;
if (!string.IsNullOrEmpty(relativePath))
{
path += relativePath;
}
outputStream = new FileStream(localFileName, FileMode.Append);
ftpsize = (FtpWebRequest)FtpWebRequest.Create(path);
ftpsize.UseBinary = true;
ftpsize.ContentOffset = size;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(path);
reqFTP.UseBinary = true;
reqFTP.KeepAlive = false;
reqFTP.ContentOffset = size;
if (_isAuth)//使用用戶身份認證
{
ftpsize.Credentials = new NetworkCredential(_userName, _password);
reqFTP.Credentials = new NetworkCredential(_userName, _password);
}
ftpsize.Method = WebRequestMethods.Ftp.GetFileSize;
FtpWebResponse re = (FtpWebResponse)ftpsize.GetResponse();
long totalBytes = re.ContentLength;
re.Close();
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
response = (FtpWebResponse)reqFTP.GetResponse();
ftpStream = response.GetResponseStream();
//更新進度
if (updateProgress != null)
{
updateProgress(localFileName.Substring(localFileName.LastIndexOf('\\') + 1, localFileName.Length - localFileName.LastIndexOf('\\') -1), (int)totalBytes, 0, (int)index);//更新進度條
}
long totalDownloadedByte = 0;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize];
readCount = ftpStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
totalDownloadedByte = readCount + totalDownloadedByte;
outputStream.Write(buffer, 0, readCount);
//更新進度
if (updateProgress != null)
{
updateProgress(localFileName.Substring(localFileName.LastIndexOf('\\') + 1, localFileName.Length - localFileName.LastIndexOf('\\') -1),(int)totalBytes, (int)totalDownloadedByte, (int)index);//更新進度條
}
readCount = ftpStream.Read(buffer, 0, bufferSize);
}
ftpStream.Close();
outputStream.Close();
response.Close();
return true;
}
catch (Exception ex)
{
return false;
throw;
}
finally
{
if (ftpStream != null)
{
ftpStream.Close();
}
if (outputStream != null)
{
outputStream.Close();
}
if (response != null)
{
response.Close();
}
}
}
}
}
2、HttpHelper類
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
namespace FileBackup.Http
{
public class HttpFileHelper
{
/// <summary>
/// 文件下載(支持斷點續傳)
/// </summary>
/// <param name="httpPath"></param>
/// <param name="saveFilePath"></param>
/// <returns></returns>
public bool DownLoadFiles(string httpPath, string saveFilePath)
{
bool flag = false;
//打開上次下載的文件
long SPosition = 0;
//實例化流對象
FileStream FStream;
//判斷要下載的文件夾是否存在
if (File.Exists(saveFilePath))
{
//打開要下載的文件
FStream = File.OpenWrite(saveFilePath);
//獲取已經下載的長度
SPosition = FStream.Length;
long serverFileLength = GetHttpLength(httpPath);
//文件是完整的,直接結束下載任務
if (SPosition == serverFileLength)
{
return true;
}
FStream.Seek(SPosition, SeekOrigin.Current);
}
else
{
//文件不保存創建一個文件
FStream = new FileStream(saveFilePath, FileMode.Create);
SPosition = 0;
}
try
{
//打開網絡連接
HttpWebRequest myRequest = (HttpWebRequest)HttpWebRequest.Create(httpPath);
if (SPosition > 0)
myRequest.AddRange((int)SPosition); //設置Range值
//向服務器請求,獲得服務器的回應數據流
Stream myStream = myRequest.GetResponse().GetResponseStream();
//定義一個字節數據
byte[] btContent = new byte[512];
int intSize = 0;
intSize = myStream.Read(btContent, 0, 512);
while (intSize > 0)
{
FStream.Write(btContent, 0, intSize);
intSize = myStream.Read(btContent, 0, 512);
}
//關閉流
FStream.Close();
myStream.Close();
flag = true;
}
catch (Exception)
{
FStream.Close();
flag = false;
}
return flag;
}
/// <summary>
/// 獲取http服務器端文件大小
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
private long GetHttpLength(string url)
{
long length = 0;
try
{
var req = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url));
req.Method = "HEAD";
req.Timeout = 5000;
var res = (HttpWebResponse)req.GetResponse();
if (res.StatusCode == HttpStatusCode.OK)
{
length = res.ContentLength;
}
res.Close();
return length;
}
catch (WebException ex)
{
return 0;
}
}
}
}
3、測試類(Program.cs)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net;
using FileBackup.Http;
namespace FileBackup
{
class Program
{
//文件序號(遞增)
static int index = 0;
static void Main(string[] args)
{
Console.WriteLine("Loading........");
string path = "ftp://xxx.xxx.xxx.xxx:8765/";
//路徑結尾不需要帶斜杠
string localPath = @"E:\FTPTestFiles";
localPath = localPath.TrimEnd('\\');
//初始化ftp服務鏈接
FTPHelper fTPHelper = new FTPHelper(path, false, null, null);
//獲取ftp根目錄下所有文件
List<string> fileList = fTPHelper.GetFileList(null, false);
if (fileList != null)
{
//路徑不存在則創建
if (!Directory.Exists(localPath))
{
Directory.CreateDirectory(localPath);
}
//下載文件到指定本地路徑
for (int i = 0; i < fileList.Count; i++)
{
Action<string, int, int, int> action = new Action<string, int, int, int>(ShowAction);
index++;
fTPHelper.FtpBrokenDownload(fileList[i], string.Format(@"{0}\{1}", localPath, fileList[i]), 0, action, index);
}
}
//獲取ftp根目錄下所有文件夾
List<string> dirctoryList = fTPHelper.GetFileList(null, true);
if (dirctoryList != null)
{
//遞歸下載文件夾下所有文件(初始父級相對路徑為空)
FilesDownLoad(fTPHelper, dirctoryList, null, localPath);
}
//http文件下載測試
HttpFileHelper httpFileHelper = new HttpFileHelper();
httpFileHelper.DownLoadFiles("http://xxxxxxx:9798/upload/190125122251440.docx", string.Format(@"{0}\{1}", localPath, "httpfile.docx"));
Console.WriteLine("End........");
Console.ReadLine();
}
/// <summary>
/// 下載文件夾列表下的所有文件(自動創建對應文件夾)
/// </summary>
/// <param name="fTPHelper"></param>
/// <param name="dirctoryList">文件夾列表</param>
/// <param name="parentRelativePath">ftp父級相對路徑</param>
/// <param name="localPath">本地存放路徑</param>
private static void FilesDownLoad(FTP.FTPHelper fTPHelper, List<string> dirctoryList, string parentRelativePath, string localPath)
{
if (dirctoryList != null)
{
for (int i = 0; i < dirctoryList.Count; i++)
{
//當前本地下載路徑
string localCurPath = string.Format(@"{0}\{1}", localPath, dirctoryList[i]); ;
//當前ftp相對路徑
string ftpCurPath = dirctoryList[i];
if (!string.IsNullOrEmpty(parentRelativePath))
{
ftpCurPath = string.Format(@"{0}\{1}", parentRelativePath, dirctoryList[i]);
}
//路徑不存在則創建
if (!Directory.Exists(localCurPath))
{
Directory.CreateDirectory(localCurPath);
}
//獲取文件夾下所有文件
List<string> subfileList = fTPHelper.GetFileList(ftpCurPath, false);
if(subfileList != null)
{
for (int j = 0; j < subfileList.Count; j++)
{
//下載文件夾下所有文件,文件名與ftp服務器上文件名保持一致(含后綴)
Action<string, int, int, int> action = new Action<string, int, int, int>(ShowAction);
index++;
fTPHelper.FtpBrokenDownload(string.Format(@"{0}\{1}", ftpCurPath, subfileList[j]), string.Format(@"{0}\{1}", localCurPath, subfileList[j]), 0, action, index);
}
}
//獲取該文件夾下所有子文件夾
List<string> subdirctoryList = fTPHelper.GetFileList(ftpCurPath, true);
if (subdirctoryList != null)
{
//遞歸下載文件夾下所有文件
FilesDownLoad(fTPHelper, subdirctoryList, ftpCurPath, localCurPath);
}
}
}
}
/// <summary>
/// 控制台進度顯示
/// </summary>
/// <param name="file"></param>
/// <param name="size"></param>
/// <param name="progress"></param>
/// <param name="rowIndex"></param>
public static void ShowAction(string file, int size, int progress, int rowIndex)
{
//命令行光標位置定位
Console.SetCursorPosition(0, rowIndex);
if (size > 0)
{
Console.WriteLine(string.Format("{0}: Total Size:{1}; Progress:{2}%", file, size, Math.Round((Double)progress*100 / (Double)size, 0)));
}
else
{
Console.WriteLine(string.Format("{0}: Total Size:{1}; Progress:{2}%", file, size, 100));
}
}
}
}
