using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Windows.Forms;
using System.Threading;
namespace SoulWorkerDownload
{
/// <summary>
/// FTP檔案上傳下載下傳
/// </summary>
public class FileUpDownload
{
#region 變量屬性
private Thread m_thread_Download = null;
/// <summary>
/// Ftp伺服器ip
/// </summary>
private string FtpServerIP = string.Empty;
/// <summary>
/// Ftp 指定使用者名
/// </summary>
private string FtpUserID = string.Empty;
/// <summary>
/// Ftp 指定使用者密碼
/// </summary>
private string FtpPassword = string.Empty;
/// <summary>
/// 遠端檔案名
/// </summary>
private string remoteFileName = string.Empty;
/// <summary>
/// 本地檔案名
/// </summary>
private string localFileName = string.Empty;
public string LocalFileName
{
get { return localFileName; }
set { localFileName = value; }
}
private MainForm mainform;
/// <summary>
/// 更新進度條
/// </summary>
public Action< long> updateProgress;
#endregion
#region 從FTP伺服器下載下傳檔案,指定本地路徑和本地檔案名
public FileUpDownload(string IP, string userID, string userPassword,string targetFileName,string saveFileName,MainForm form)
{
FtpServerIP = IP;
FtpUserID = userID;
FtpPassword = userPassword;
remoteFileName = targetFileName;
localFileName = saveFileName;
mainform = form;
}
public void StartSingleDownload()
{
m_thread_Download = new Thread(new ThreadStart(FtpDownloadFile));
m_thread_Download.SetApartmentState(ApartmentState.STA);
m_thread_Download.Priority = ThreadPriority.Highest;
m_thread_Download.Start();
}
/// <summary>
/// 停止下載下傳
/// </summary>
public void AbortSingleDownload()
{
if (m_thread_Download != null && m_thread_Download.IsAlive )
{
if (m_thread_Download.ThreadState == ThreadState.Suspended)
m_thread_Download.Resume();
//if(Step.CURRENT_STEP != Step.State._ProcessState_Restart)
m_thread_Download.Abort();
}
}
/// <summary>
/// 暫停。挂起線程,或者如果線程已挂起,則不起作用
/// </summary>
/// <param name="_parameter"></param>
public void SuspendSingleDownload()
{
if (m_thread_Download != null && m_thread_Download.IsAlive == true)
{
m_thread_Download.Suspend();
}
}
public void ResumeSingleDownload()
{
bool isAlive = m_thread_Download.IsAlive;
ThreadState state = m_thread_Download.ThreadState;
if (m_thread_Download != null)
{
m_thread_Download.Resume();
}
}
/// <summary>
/// 判斷線程是否結束
/// </summary>
public bool IsAbortThreadOrStop()
{
bool isAbort = false;
//bool alive = m_thread_Download.IsAlive;
if (m_thread_Download == null)
return true;
if ((m_thread_Download.ThreadState & ThreadState.Aborted) != 0)
{
isAbort = true;
}
if (!m_thread_Download.IsAlive)
{
isAbort = true;
}
return isAbort;
}
/// <summary>
/// 從FTP伺服器下載下傳檔案,指定本地路徑和本地檔案名
/// </summary>
/// <param name="remoteFileName">遠端檔案名</param>
/// <param name="localFileName">儲存本地的檔案名(包含路徑)</param>
/// <param name="updateProgress">報告進度的處理(第一個參數:總大小,第二個參數:目前進度)</param>
/// <returns>是否下載下傳成功</returns>
public bool FtpDownload(string remoteFileName, string localFileName, Action<int, int> updateProgress = null)
{
FtpWebRequest reqFTP, ftpsize;
Stream ftpStream = null;
FtpWebResponse response = null;
FileStream outputStream = null;
try
{
outputStream = new FileStream(localFileName, FileMode.Create);
if (FtpServerIP == null || FtpServerIP.Trim().Length == 0)
{
throw new Exception("ftp下載下傳目标伺服器位址未設定!");
}
Uri uri = new Uri("ftp://" + FtpServerIP + "/" + remoteFileName);
ftpsize = (FtpWebRequest)FtpWebRequest.Create(uri);
ftpsize.UseBinary = true;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(uri);
reqFTP.UseBinary = true;
reqFTP.KeepAlive = false;
ftpsize.Credentials = new NetworkCredential(FtpUserID, FtpPassword);
reqFTP.Credentials = new NetworkCredential(FtpUserID, FtpPassword);
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((int)totalBytes, 0);//更新進度條
}
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((int)totalBytes, (int)totalDownloadedByte);//更新進度條
}
readCount = ftpStream.Read(buffer, 0, bufferSize);
}
ftpStream.Close();
outputStream.Close();
response.Close();
return true;
}
catch (Exception)
{
return false;
throw;
}
finally
{
if (ftpStream != null)
{
ftpStream.Close();
}
if (outputStream != null)
{
outputStream.Close();
}
if (response != null)
{
response.Close();
}
}
}
bool isShowIOError = false;
/// <summary>
/// 從FTP伺服器下載下傳檔案,指定本地路徑和本地檔案名(支援斷點下載下傳)
/// </summary>
/// <param name="remoteFileName">遠端檔案名</param>
/// <param name="localFileName">儲存本地的檔案名(包含路徑)</param>
/// <param name="ifCredential">是否啟用身份驗證(false:表示允許使用者匿名下載下傳)</param>
/// <param name="size">已下載下傳檔案流大小</param>
/// <param name="updateProgress">報告進度的處理(第一個參數:總大小,第二個參數:目前進度)</param>
/// <returns>是否下載下傳成功</returns>
public bool FtpBrokenDownload(string remoteFileName, string tempLocalFileName, long size, Action<long> updateProgress = null)
{
bool isFinish = false;
FtpWebRequest reqFTP, ftpsize;
Stream ftpStream = null;
FtpWebResponse response = null;
FileStream outputStream = null;
long totalBytes = 0;
long totalDownloadedByte = size;
try
{
Thread primaryThread = Thread.CurrentThread;
// string name = "FtpDownload" + primaryThread.ManagedThreadId;
// MessageBox.Show(name
if (FtpServerIP == null || FtpServerIP.Trim().Length == 0)
{
throw new Exception("ftp下載下傳目标伺服器位址未設定!");
}
Uri uri = new Uri("ftp://" + FtpServerIP + "/" + remoteFileName);
ftpsize = (FtpWebRequest)FtpWebRequest.Create(uri);
ftpsize.UseBinary = true;
ftpsize.ContentOffset = size;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(uri);
reqFTP.UseBinary = true;
reqFTP.KeepAlive = false;
reqFTP.ContentOffset = size;
ftpsize.Credentials = GetCredentials(); //new NetworkCredential(FtpUserID, FtpPassword);
reqFTP.Credentials = GetCredentials();// new NetworkCredential(FtpUserID, FtpPassword);
ftpsize.Method = WebRequestMethods.Ftp.GetFileSize;
FtpWebResponse re = (FtpWebResponse)ftpsize.GetResponse();
totalBytes = re.ContentLength;
re.Close();
if (size == totalBytes)
{
return true;
}
else
Step.CURRENT_STEP = Step.State._ProcessState_Loading;
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
response = (FtpWebResponse)reqFTP.GetResponse();
ftpStream = response.GetResponseStream();
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize];
readCount = ftpStream.Read(buffer, 0, bufferSize);
using (outputStream = new FileStream(tempLocalFileName, FileMode.Append))
{
while (readCount > 0)
{
outputStream.Write(buffer, 0, readCount);
totalDownloadedByte = readCount + totalDownloadedByte;
//更新進度
if (updateProgress != null)
{
updateProgress(totalDownloadedByte);//更新進度條
}
try
{
readCount = ftpStream.Read(buffer, 0, bufferSize);
}
catch
{
break;
}
}
}
try
{
response.Close();
ftpStream.Close();
}
catch { }
outputStream.Close();
if (totalDownloadedByte == totalBytes)
{
isFinish = true;
}
}
catch(WebException e)
{
FtpWebResponse res = (FtpWebResponse)e.Response;
string code = "下載下傳伺服器連接配接失敗,錯誤碼:" + res.StatusCode;
MessageBox.Show(code);
}
catch (IOException e)
{
isShowIOError = true;
MessageBox.Show(e.Message);
}
finally
{
try
{
if (ftpStream != null)
{
ftpStream.Close();
}
if (outputStream != null)
{
outputStream.Close();
}
if (response != null)
{
response.Close();
}
}
catch { }
}
if (totalDownloadedByte == totalBytes)
{
isFinish = true;
}
return isFinish;
}
/// <summary>
/// 從FTP伺服器下載下傳檔案,指定本地路徑和本地檔案名
/// </summary>
/// <param name="remoteFileName">遠端檔案名</param>
/// <param name="localFileName">儲存本地的檔案名(包含路徑)</param>
/// <param name="updateProgress">報告進度的處理(第一個參數:總大小,第二個參數:目前進度)</param>
/// <param name="brokenOpen">是否斷點下載下傳:true 會在localFileName 找是否存在已經下載下傳的檔案,并計算檔案流大小</param>
/// <returns>是否下載下傳成功</returns>
//public static bool FtpDownloadFile(string remoteFileName, string localFileName, bool brokenOpen, Action<int, int> updateProgress = null)
public void FtpDownloadFile()
{
long size0 = 0;
long size1 = 0;
if (File.Exists(localFileName))
{
using (FileStream outputStream = new FileStream(localFileName, FileMode.Open))
{
size0 = outputStream.Length;
}
}
//逾時2次内再重連
while (!FtpBrokenDownload(remoteFileName, localFileName, size0, updateProgress))
{
if (Step.CURRENT_STEP != Step.State._ProcessState_Loading)
{
AbortSingleDownload();
return;
}
if (File.Exists(localFileName))
{
using (FileStream outputStream = new FileStream(localFileName, FileMode.Open))
{
size1 = outputStream.Length;
}
}
if (size1 == size0)
{
//MessageBox.Show("下載下傳伺服器連接配接失敗,請檢查網絡并確定防火牆允許SoulWorkerDownload聯網!");
mainform.AppEnd();
return;
}
else
{
size0 = size1;
}
}
}
#endregion
#region ftp檔案工具類
/// <summary>
/// 檢查ftp上該檔案是否存在
/// </summary>
/// <param name="strFilename"></param>
/// <returns></returns>
public bool FtpFileExists()
{
try
{
long size = GetFileSize();
if (size > 0)
return true;
return false;
}
catch (Exception ex)
{
if (ex is WebException)
{
if (ex.Message.Contains("550"))
{
return false;
}
else
{
throw;
}
}
else
{
throw;
}
}
}
/// <summary>
/// 擷取檔案的大小
/// </summary>
/// <param name="strFilename"></param>
/// <returns></returns>
public long GetFileSize()
{
long fileBytes = 0;
FtpWebResponse re =null;
try
{
if (FtpServerIP == null || FtpServerIP.Trim().Length == 0)
{
throw new Exception("ftp下載下傳目标伺服器位址未設定!");
}
string uri = "ftp://" + FtpServerIP + "/" + remoteFileName;
FtpWebRequest ftp = GetRequest(uri);
ftp.Method = WebRequestMethods.Ftp.GetFileSize;
re = (FtpWebResponse)ftp.GetResponse();
fileBytes = re.ContentLength;
re.Close();
}
catch (WebException ex)
{
if (!isShowIOError)
{
FtpWebResponse res = (FtpWebResponse)ex.Response;
string code = "下載下傳伺服器連接配接失敗,錯誤碼:" + res.StatusCode;
MessageBox.Show(code);
}
mainform.AppEnd();
}
finally
{
if (re != null)
re.Close();
}
return fileBytes;
}
//請求檢視檔案夾
private FtpWebRequest GetRequest(string strURI)
{
FtpWebRequest result = (FtpWebRequest)FtpWebRequest.Create(strURI);
result.Credentials = GetCredentials();//建立請求
result.KeepAlive = false;
result.Timeout = 20000;
result.UsePassive = false;
return result;
}
private ICredentials GetCredentials()
{
return new NetworkCredential(FtpUserID, FtpPassword);
}
#endregion
}
}