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; reqFTP.EnableSsl = true; 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 { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(remoteFilepath); reqFTP.EnableSsl = true; 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(Exception ex) { 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); } } } } }