391 lines
12 KiB
C#
391 lines
12 KiB
C#
|
using GameBackup3H3.DbOp;
|
|||
|
using ryCommon;
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using System.Text;
|
|||
|
using WinSCP;
|
|||
|
|
|||
|
namespace FTPop
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// FTP管理
|
|||
|
/// </summary>
|
|||
|
public class FTPWinSCP : IFTP, IDisposable
|
|||
|
{
|
|||
|
private bool disposed = false;
|
|||
|
readonly Session session = new Session();
|
|||
|
public string CurRemoteFolder { get; private set; } = "";
|
|||
|
private FTPInfo _ftpinfo = null;
|
|||
|
/// <summary>
|
|||
|
/// 打开FTP
|
|||
|
/// </summary>
|
|||
|
/// <param name="ftpinfo"></param>
|
|||
|
public int Open(FTPInfo ftpinfo)
|
|||
|
{
|
|||
|
if(ftpinfo==null)
|
|||
|
{
|
|||
|
return -1;
|
|||
|
}
|
|||
|
_ftpinfo = ftpinfo;
|
|||
|
SessionOptions sessionOptions = new SessionOptions
|
|||
|
{
|
|||
|
Protocol = Protocol.Ftp,
|
|||
|
HostName = ftpinfo.IP,
|
|||
|
PortNumber = ftpinfo.Port,
|
|||
|
UserName = ftpinfo.UserName,
|
|||
|
Password = ftpinfo.Pwd,
|
|||
|
};
|
|||
|
CurRemoteFolder = ftpinfo.RemoteDir;
|
|||
|
if (ftpinfo.Encrypt > 0)
|
|||
|
{
|
|||
|
sessionOptions.FtpSecure = ftpinfo.Encrypt == 2 ? FtpSecure.Explicit : FtpSecure.Implicit;
|
|||
|
sessionOptions.GiveUpSecurityAndAcceptAnyTlsHostCertificate = true;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
sessionOptions.FtpSecure = FtpSecure.None;
|
|||
|
}
|
|||
|
if (FileTransferProgress != null)
|
|||
|
{
|
|||
|
session.FileTransferProgress += Session_FileTransferProgress; ;
|
|||
|
}
|
|||
|
try
|
|||
|
{
|
|||
|
session.Open(sessionOptions);
|
|||
|
if (session.Opened)
|
|||
|
{
|
|||
|
isopen = true;
|
|||
|
return 1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
isopen = false;
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
catch(Exception ex)
|
|||
|
{
|
|||
|
isopen = false;
|
|||
|
ErrorMsg = ex.Message;
|
|||
|
return -2;
|
|||
|
}
|
|||
|
}
|
|||
|
private bool isopen = false;
|
|||
|
/// <summary>
|
|||
|
/// ftp是否打开着
|
|||
|
/// </summary>
|
|||
|
public bool IsOpen
|
|||
|
{
|
|||
|
get {
|
|||
|
try {
|
|||
|
return session.Opened && isopen;
|
|||
|
}
|
|||
|
catch { return false; }
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// ftp是否打开着
|
|||
|
/// </summary>
|
|||
|
public int ReConnect
|
|||
|
{
|
|||
|
get { return Open(_ftpinfo); }
|
|||
|
}
|
|||
|
private void Session_FileTransferProgress(object sender, WinSCP.FileTransferProgressEventArgs e)
|
|||
|
{
|
|||
|
var progress= new FileTransferProgressEventArgs()
|
|||
|
{
|
|||
|
Cancel = e.Cancel,
|
|||
|
LocalPath = e.FileName,
|
|||
|
FileProgress=e.FileProgress,
|
|||
|
IsComplete=e.FileProgress==1
|
|||
|
};
|
|||
|
FileTransferProgress?.Invoke(this, progress);
|
|||
|
if (progress.Cancel) { e.Cancel = progress.Cancel; }
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 关闭FTP
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
public int Close()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (session.Opened)
|
|||
|
{ session.Close(); }
|
|||
|
session?.Dispose();
|
|||
|
return 1;
|
|||
|
}
|
|||
|
catch { return 0; }
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 移除文件
|
|||
|
/// </summary>
|
|||
|
/// <param name="remotePath"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public int RemoveFiles(string remotePath)
|
|||
|
{
|
|||
|
var result= session.RemoveFiles(remotePath);
|
|||
|
return result.IsSuccess?1:-1;
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 移动文件
|
|||
|
/// </summary>
|
|||
|
/// <param name="fromPath"></param>
|
|||
|
/// <param name="toPath"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public int MoveFile(string fromPath, string toPath)
|
|||
|
{
|
|||
|
session.MoveFile(fromPath, toPath);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 删除文件
|
|||
|
/// </summary>
|
|||
|
/// <param name="remotePath"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public int DelFile(string remotePath) {
|
|||
|
try {
|
|||
|
session.RemoveFiles(remotePath);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
catch { return -1; }
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 移动文件
|
|||
|
/// </summary>
|
|||
|
/// <param name="DirPath"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public int CreateDir(string DirPath)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
session.CreateDirectory(DirPath);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
catch
|
|||
|
{
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 文件是否存在
|
|||
|
/// </summary>
|
|||
|
/// <param name="remotePath"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public bool FileExists(string remotePath)
|
|||
|
{
|
|||
|
if(remotePath.Length==0 || remotePath == "/") { return true; }
|
|||
|
try
|
|||
|
{
|
|||
|
return session.FileExists(remotePath);
|
|||
|
}
|
|||
|
catch { return false; }
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 文件大小
|
|||
|
/// </summary>
|
|||
|
/// <param name="remotePath"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public Int64 FileSize(string remotePath)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
return session.GetFileInfo(remotePath).Length;
|
|||
|
}
|
|||
|
catch { return -1; }
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 文件最后修改时间
|
|||
|
/// </summary>
|
|||
|
/// <param name="remotePath"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public DateTime FileLastWriteTime(string remotePath)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
return session.GetFileInfo(remotePath).LastWriteTime;
|
|||
|
}
|
|||
|
catch { return new DateTime(2000,1,1); }
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 文件信息
|
|||
|
/// </summary>
|
|||
|
/// <param name="remotePath"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public RemoteFileInfo GetFileInfo(string remotePath)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
var info = session.GetFileInfo(remotePath);
|
|||
|
return new RemoteFileInfo() { LastWriteTime = info.LastWriteTime, Length = info.Length, Name = info.Name, IsDirectory = info.IsDirectory };
|
|||
|
}
|
|||
|
catch { return new RemoteFileInfo(); }
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 显示文件夹列表
|
|||
|
/// </summary>
|
|||
|
/// <param name="CurFolder"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public List<RemoteFileInfo> ListDirectory(string CurFolder, out string error)
|
|||
|
{
|
|||
|
error = "";
|
|||
|
var list = new List<RemoteFileInfo>();
|
|||
|
try
|
|||
|
{
|
|||
|
var result = session.ListDirectory(CurFolder);
|
|||
|
for (int i = 0; i < result.Files.Count; i++)
|
|||
|
{
|
|||
|
var file = result.Files[i];
|
|||
|
list.Add(new RemoteFileInfo()
|
|||
|
{
|
|||
|
FullName = file.FullName,
|
|||
|
IsDirectory = file.IsDirectory,
|
|||
|
Name = file.Name,
|
|||
|
Length = file.Length,
|
|||
|
LastWriteTime = file.LastWriteTime
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
catch(Exception ex)
|
|||
|
{
|
|||
|
isopen = false;
|
|||
|
error = ex.Message;
|
|||
|
}
|
|||
|
return list;
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 上传
|
|||
|
/// </summary>
|
|||
|
/// <param name="localPath"></param>
|
|||
|
/// <param name="remotePath"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public int Upload(string localPath, string remotePath)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
TransferOptions transferOptions = new TransferOptions
|
|||
|
{
|
|||
|
TransferMode = TransferMode.Binary,
|
|||
|
OverwriteMode= OverwriteMode.Overwrite,
|
|||
|
};
|
|||
|
TransferOperationResult transferResult;
|
|||
|
transferResult =
|
|||
|
session.PutFiles(localPath, remotePath, false, transferOptions);
|
|||
|
//Throw on any error
|
|||
|
transferResult.Check();
|
|||
|
if (transferResult.IsSuccess)
|
|||
|
{
|
|||
|
if (System.IO.Directory.Exists(localPath))
|
|||
|
{ return 1; }
|
|||
|
else
|
|||
|
{
|
|||
|
if (FileSize(remotePath) == RyFiles.GetFileSize(localPath))
|
|||
|
{
|
|||
|
return 1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ErrorMsg = "文件不完整。";
|
|||
|
return -3;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return -2;
|
|||
|
}
|
|||
|
}
|
|||
|
catch(Exception ex)
|
|||
|
{
|
|||
|
ErrorMsg = ex.Message;
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
/// <summary>
|
|||
|
/// 下载
|
|||
|
/// </summary>
|
|||
|
/// <param name="remotePath"></param>
|
|||
|
/// <param name="localPath"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public int Download(string remotePath, string localPath)
|
|||
|
{
|
|||
|
if(!RyFiles.FileOrDirExist(System.IO.Path.GetDirectoryName(localPath)))
|
|||
|
{
|
|||
|
RyFiles.CreateDirectory(System.IO.Path.GetDirectoryName(localPath));
|
|||
|
}
|
|||
|
try
|
|||
|
{
|
|||
|
TransferOptions transferOptions = new TransferOptions
|
|||
|
{
|
|||
|
TransferMode = TransferMode.Binary,
|
|||
|
OverwriteMode = OverwriteMode.Overwrite
|
|||
|
};
|
|||
|
TransferOperationResult transferResult;
|
|||
|
transferResult =
|
|||
|
session.GetFiles(remotePath, localPath, false, transferOptions);
|
|||
|
//Throw on any error
|
|||
|
transferResult.Check();
|
|||
|
if (transferResult.IsSuccess)
|
|||
|
{
|
|||
|
if (FileSize(remotePath) == RyFiles.GetFileSize(localPath))
|
|||
|
{
|
|||
|
return 1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ErrorMsg = "文件不完整。";
|
|||
|
return -3;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return -2;
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
ErrorMsg = ex.Message;
|
|||
|
return -1;
|
|||
|
}
|
|||
|
}
|
|||
|
public string ErrorMsg { get; set; } = "";
|
|||
|
/// <summary>
|
|||
|
/// 文件传输事件
|
|||
|
/// </summary>
|
|||
|
public event FileTransferProgressEventHandler FileTransferProgress;
|
|||
|
~FTPWinSCP()
|
|||
|
{
|
|||
|
Dispose(false);
|
|||
|
}
|
|||
|
public void Dispose()
|
|||
|
{
|
|||
|
Dispose(true);
|
|||
|
GC.SuppressFinalize(this);
|
|||
|
}
|
|||
|
protected virtual void Dispose(bool disposing)
|
|||
|
{
|
|||
|
if (!this.disposed)
|
|||
|
{
|
|||
|
Close();
|
|||
|
// If disposing equals true, dispose all managed
|
|||
|
// and unmanaged resources.
|
|||
|
if (disposing)
|
|||
|
{
|
|||
|
// Dispose managed resources.
|
|||
|
session.Dispose();
|
|||
|
}
|
|||
|
// Release unmanaged resources. If disposing is false,
|
|||
|
// only the following code is executed.
|
|||
|
// Note that this is not thread safe.
|
|||
|
// Another thread could start disposing the object
|
|||
|
// after the managed resources are disposed,
|
|||
|
// but before the disposed flag is set to true.
|
|||
|
// If thread safety is necessary, it must be
|
|||
|
// implemented by the client.
|
|||
|
}
|
|||
|
disposed = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|