using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TestTool.RemoteTriggerAPP
{
public class FtpState
{
private ManualResetEvent wait;
private FtpWebRequest request;
private string fileName;
private Exception operationException = null;
private FtpStatusCode status;
public FtpState()
{
wait = new ManualResetEvent(false);
}
public ManualResetEvent OperationComplete
{
get { return wait; }
}
public FtpWebRequest Request
{
get { return request; }
set { request = value; }
}
public string FileName
{
get { return fileName; }
set { fileName = value; }
}
public Exception OperationException
{
get { return operationException; }
set { operationException = value; }
}
public FtpStatusCode StatusCode
{
get { return status; }
set { status = value; }
}
}
public class FTPClient
{
public delegate void UploadDataCompletedEventHandler(FtpState state);
public delegate void UploadDataProgressEventHandler(double percent);
public event UploadDataCompletedEventHandler OnUploadSuccessful;
public event UploadDataCompletedEventHandler OnUploadFail;
public event UploadDataProgressEventHandler OnUploadProgress;
private int uploadTimeOut = 5 * 1000 * 60;
public string Host
{
private set; get;
}
public string UesrName
{
private set; get;
}
public string Password
{
private set; get;
}
public int UploadTimeOut
{
get
{
return uploadTimeOut;
}
set
{
uploadTimeOut = value;
}
}
public FTPClient(string host, string usrName, string password)
{
Host = host;
UesrName = usrName;
Password = password;
}
///
/// 上傳檔案到FTPServer(斷點續傳)
///
/// 本地上傳檔案的路徑
/// FTPServer上的存放路徑
public bool FtpUploadBroken(string uploadFilePath, string uploadFtpPath)
{
if (uploadFtpPath == null)
{
uploadFtpPath = "";
}
string newFileName = string.Empty;
bool success = true;
FileInfo fileInf = new FileInfo(uploadFilePath);
long allbye = (long)fileInf.Length;
long startfilesize = GetFileSize(uploadFtpPath);
if (startfilesize >= allbye)
{
return true;
}
long startbye = startfilesize;
FtpWebRequest reqFTP;
// 根据uri创建FtpWebRequest对象
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uploadFtpPath));
// ftp用户名和密码
reqFTP.Credentials = new NetworkCredential(UesrName, Password);
// 默认为true,连接不会被关闭
// 在一个命令之后被执行
reqFTP.KeepAlive = false;
// 指定执行什么命令
reqFTP.Method = WebRequestMethods.Ftp.AppendFile;
// 指定数据传输类型
reqFTP.UseBinary = true;
// 上传文件时通知服务器文件的大小
reqFTP.ContentLength = fileInf.Length;
int buffLength = 2048000;// 缓冲大小设置为200kb
byte[] buff = new byte[buffLength];
// 打开一个文件流 (System.IO.FileStream) 去读上传的文件
using (FileStream fs = fileInf.OpenRead())
{
Stream strm = null;
try
{
// 把上传的文件写入流
strm = reqFTP.GetRequestStream();
// 每次读文件流的2kb
fs.Seek(startfilesize, 0);
int contentLen = fs.Read(buff, 0, buffLength);
// 流内容没有结束
while (contentLen != 0)
{
// 把内容从file stream 写入 upload stream
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
startbye += contentLen;
double percent = (double)((decimal)startbye / reqFTP.ContentLength) * 100;
OnUploadProgress?.Invoke(percent);
}
// 关闭两个流
strm.Close();
fs.Close();
}
catch(Exception ex)
{
success = false;
}
finally
{
if (fs != null)
{
fs.Close();
}
if (strm != null)
{
strm.Close();
}
}
}
return success;
}
///
/// 獲取已上傳檔案大小
///
/// 服务器文件路径
///
private long GetFileSize(string remoteFilepath)
{
long filesize = 0;
try
{
FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(remoteFilepath);
reqFTP.KeepAlive = false;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(UesrName, Password);//用户,密码
reqFTP.Method = WebRequestMethods.Ftp.GetFileSize;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
filesize = response.ContentLength;
return filesize;
}
catch
{
return 0;
}
}
///
/// 上傳檔案到FTPServer
///
/// 本地上傳檔案的路徑
/// FTPServer上的存放路徑
public void UploadFile(string uploadFilePath, string uploadFtpPath)
{
Uri target = new Uri(uploadFtpPath);
FtpState state = new FtpState();
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(target);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(UesrName, Password);
state.Request = request;
state.FileName = uploadFilePath;
// Asynchronously get the stream for the file contents.
request.BeginGetRequestStream(
new AsyncCallback(EndGetStreamCallback),
state
);
ThreadPool.RegisterWaitForSingleObject(state.OperationComplete, new WaitOrTimerCallback(TimeoutCallback), state, UploadTimeOut, true);
}
private void EndGetStreamCallback(IAsyncResult ar)
{
FtpState state = (FtpState)ar.AsyncState;
Stream requestStream = null;
// End the asynchronous call to get the request stream.
try
{
using (requestStream = state.Request.EndGetRequestStream(ar))
{
// Copy the file contents to the request stream.
const int bufferLength = 2048;
byte[] buffer = new byte[bufferLength];
int count = 0;
int readBytes = 0;
using (FileStream stream = File.OpenRead(state.FileName))
{
do
{
readBytes = stream.Read(buffer, 0, bufferLength);
requestStream.Write(buffer, 0, readBytes);
count += readBytes;
}
while (readBytes != 0);
}
Console.WriteLine("Writing {0} bytes to the stream.", count);
// IMPORTANT: Close the request stream before sending the request.
requestStream.Close();
}
// Asynchronously get the response to the upload request.
state.Request.BeginGetResponse(
new AsyncCallback(EndGetResponseCallback),
state
);
}
// Return exceptions to the main application thread.
catch (Exception e)
{
Console.WriteLine("Could not get the request stream.");
state.OperationException = e;
state.OperationComplete.Set();
//if (OnUploadFail != null)
// OnUploadFail(state);
}
}
private void EndGetResponseCallback(IAsyncResult ar)
{
FtpState state = (FtpState)ar.AsyncState;
FtpWebResponse response = null;
try
{
response = (FtpWebResponse)state.Request.EndGetResponse(ar);
response.Close();
state.StatusCode = response.StatusCode;
state.OperationComplete.Set();
}
// Return exceptions to the main application thread.
catch (Exception e)
{
//Console.WriteLine("Error getting response.");
state.OperationException = e;
state.OperationComplete.Set();
//if (OnUploadFail != null)
// OnUploadFail(state);
}
}
private void TimeoutCallback(object state, bool timedOut)
{
FtpState _state = state as FtpState;
if (timedOut)
{
_state.Request.Abort();
if (OnUploadFail != null)
OnUploadFail(_state);
}
else
{
if (_state.StatusCode == FtpStatusCode.ClosingData)
{
if (OnUploadSuccessful != null)
OnUploadSuccessful(_state);
}
else
{
if (OnUploadFail != null)
OnUploadFail(_state);
}
}
}
}
}