Files
2025-08-26 08:37:44 +08:00

767 lines
26 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Avalonia.Threading;
using MES.Utility.Core;
using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using Ursa.Controls;
using .Base;
using .Utility.Network;
namespace .ViewModel._02网络相关
{
public class FTP客户端ViewModel : ViewModelBase
{
public List<Encoding> EncodingList { get; set; } = new List<Encoding>() { Encoding.UTF8 };
public List<string> StrEncodingList { get; set; } = new List<string>() { "UTF-8" };
public int EncodingIndex { get; set; } = 0;
private object _lock = new object();
private List<string> msgList = new List<string>();
public string Message
{
get
{
lock (_lock)
{
return msgList.GetStrArray("\r\n");
}
}
set
{
lock (_lock)
{
msgList.Add(value);
}
NotifyPropertyChanged();
}
}
public string IpAddress { get; set; } = "127.0.0.1";
public string UserName { get; set; } = "admin";
public string Password { get; set; } = "123456";
public int Port { get; set; } = 21;
public bool IsAnonymous { get; set; } = false;
public bool EnableFlag1 { get; set; } = true;
public bool EnableFlag2 { get; set; } = false;
private FtpHelper ftp;
public DelegateCommand ConnectCmd { get; set; }
public DelegateCommand DisconnectCmd { get; set; }
public DelegateCommand LocalDoubleClickCommand { get; set; }
public DelegateCommand LocalHomeClickCommand { get; set; }
public DelegateCommand RemoteHomeClickCommand { get; set; }
public DelegateCommand RemoteDoubleClickCommand { get; set; }
public DelegateCommand DownloadClickCommand { get; set; }
public DelegateCommand UploadClickCommand { get; set; }
public DelegateCommand RemoteRenameClickCommand { get; set; }
public DelegateCommand RemoteDeleteClickCommand { get; set; }
public string LocalPath1 { get; set; } = "本地";
public string CurrentLocalPath { get; set; } = "";
public ObservableCollection<MyDir> LocalTree { get; set; }
public MyDir LocalTreeSelectedItem { get; set; } = null;
public string RemotePath1 { get; set; } = "远程";
public string CurrentRemotePath { get; set; } = "";
public ObservableCollection<MyDir> RemoteTree { get; set; }
public MyDir RemoteTreeSelectedItem { get; set; } = null;
public FTP客户端ViewModel()
{
LocalTree = GetFoldersAndFiles();
ConnectCmd = new DelegateCommand(ConnectCmdFunc);
DisconnectCmd = new DelegateCommand(DisconnectCmdFunc);
RemoteHomeClickCommand = new DelegateCommand(RemoteHomeClickCommandFunc);
LocalHomeClickCommand = new DelegateCommand(LocalHomeClickCommandFunc);
LocalDoubleClickCommand = new DelegateCommand(LocalDoubleClickCommandFunc);
RemoteDoubleClickCommand = new DelegateCommand(RemoteDoubleClickCommandFunc);
DownloadClickCommand = new DelegateCommand(DownloadClickCommandFunc);
UploadClickCommand = new DelegateCommand(UploadClickCommandFunc);
RemoteDeleteClickCommand = new DelegateCommand(RemoteDeleteClickCommandFunc);
RemoteRenameClickCommand = new DelegateCommand(RemoteRenameClickCommandFunc);
}
private void ConnectCmdFunc(object obj)
{
if (IsAnonymous)
{
try
{
ftp = new FtpHelper(IpAddress, Port, EncodingList[EncodingIndex]);
RemoteTree = GetRemoteFoldersAndFiles();
}
catch
{
GlobalValues.Error("FTP连接失败");
return;
}
}
else
{
try
{
ftp = new FtpHelper(IpAddress, Port, UserName, Password, EncodingList[EncodingIndex]);
RemoteTree = GetRemoteFoldersAndFiles();
}
catch
{
GlobalValues.Error("FTP连接失败");
return;
}
}
EnableFlag1 = false;
EnableFlag2 = true;
}
private void DisconnectCmdFunc(object obj)
{
ftp = null;
RemoteTree = new ObservableCollection<MyDir>();
RemotePath1 = "远程";
CurrentRemotePath = "";
EnableFlag1 = true;
EnableFlag2 = false;
}
private void RemoteDoubleClickCommandFunc(object obj)
{
try
{
MyDir current = (MyDir)obj;
if (current == null)
return;
if (current.IsBack)
{
string path = CurrentRemotePath;
if (path.EndsWith("/"))
path = path.Substring(0, path.Length - 1);
int index = path.LastIndexOf("/");
if (index == -1)
{
path = "";
}
else
{
path = path.Substring(0, index + 1);
}
if (path == "")
{
CurrentRemotePath = "";
RemotePath1 = "远程";
}
else
{
CurrentRemotePath = path;
RemotePath1 = "远程:" + CurrentRemotePath;
}
RemoteTree = GetRemoteFoldersAndFiles();
return;
}
//文件不能双击
if (!current.IsDirectory)
{
return;
}
CurrentRemotePath = current.Path;
RemotePath1 = "远程:" + CurrentRemotePath;
RemoteTree = GetRemoteFoldersAndFiles();
}
catch (Exception ex)
{
GlobalValues.Error("FTP连接失败");
DisconnectCmdFunc(null);
}
}
private void LocalDoubleClickCommandFunc(object obj)
{
MyDir current = (MyDir)obj;
if (current == null)
return;
if (current.IsBack)
{
string path = CurrentLocalPath;
if (path.EndsWith("/"))
path = path.Substring(0, path.Length - 1);
int index = path.LastIndexOf("/");
if (index == -1)
{
path = "";
}
else
{
path = path.Substring(0, index + 1);
}
if (path == "")
{
CurrentLocalPath = "";
LocalPath1 = "本地";
}
else
{
CurrentLocalPath = path.Replace("\\", "/");
LocalPath1 = "本地:" + CurrentLocalPath;
}
LocalTree = GetFoldersAndFiles();
return;
}
//文件不能双击
if (!current.IsDirectory)
{
return;
}
CurrentLocalPath = current.Path;
LocalPath1 = "本地:" + CurrentLocalPath;
LocalTree = GetFoldersAndFiles();
}
private ObservableCollection<MyDir> GetRemoteFoldersAndFiles()
{
ObservableCollection<MyDir> list = new ObservableCollection<MyDir>();
List<FtpFileInfo> list2 = ftp.GetList(CurrentRemotePath).OrderByDescending(it => it.IsDirectory).ToList();
if (CurrentRemotePath != "")
{
list.Add(new MyDir
{
Name = $"...",
Path = $"",
IsDirectory = true,
IsBack = true,
});
}
foreach (var ftpFileInfo in list2)
{
if (ftpFileInfo.IsDirectory)
{
list.Add(new MyDir
{
Name = $"{ftpFileInfo.Name}",
Path = $"{CurrentRemotePath}{ftpFileInfo.Name}/",
IsDirectory = true
});
}
else
{
list.Add(new MyDir
{
Name = $"{ftpFileInfo.Name}",
Path = $"{CurrentRemotePath}{ftpFileInfo.Name}",
IsDirectory = false
});
}
}
return list;
}
private ObservableCollection<MyDir> GetFoldersAndFiles()
{
ObservableCollection<MyDir> list = new ObservableCollection<MyDir>();
if (CurrentLocalPath == "")
{
list.Add(new MyDir
{
Name = "桌面",
Path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory).Replace("\\", "/"),
IsDirectory = true
});
// 获取所有盘符
DriveInfo[] allDrives = DriveInfo.GetDrives();
// 过滤出固态硬盘SSD和机械硬盘HDD
List<string> systemDrives = allDrives.Where(drive => drive.IsReady) // 确保驱动器已准备好访问
.Where(drive => drive.DriveType == DriveType.Fixed) // 仅固定类型的驱动器
.Select(drive => drive.Name.Substring(0, 1)) // 获取盘符
.ToList();
// 输出系统盘符
foreach (var drive in systemDrives)
{
list.Add(new MyDir
{
Name = $"{drive}",
Path = $"{drive}:/",
IsDirectory = true
});
}
}
else
{
list.Add(new MyDir
{
Name = "...",
Path = "",
IsDirectory = true,
IsBack = true,
});
List<string> dirList = Directory.GetDirectories(CurrentLocalPath).Select(it => it.Replace("\\", "/")).ToList();
foreach (string dirPath in dirList)
{
list.Add(new MyDir
{
Name = System.IO.Path.GetFileName(dirPath),
Path = dirPath + "/",
IsDirectory = true,
});
}
List<string> fileList = Directory.GetFiles(CurrentLocalPath).Select(it => it.Replace("\\", "/")).ToList();
foreach (string filePath in fileList)
{
list.Add(new MyDir
{
Name = System.IO.Path.GetFileName(filePath),
Path = filePath,
IsDirectory = false,
});
}
}
return list;
}
private void LocalHomeClickCommandFunc(object obj)
{
CurrentLocalPath = "";
LocalPath1 = "本地";
LocalTree = GetFoldersAndFiles();
}
private void RemoteHomeClickCommandFunc(object obj)
{
try
{
CurrentRemotePath = "";
RemotePath1 = "远程";
RemoteTree = GetRemoteFoldersAndFiles();
}
catch (Exception ex)
{
GlobalValues.Error("FTP连接失败");
DisconnectCmdFunc(null);
}
}
/// <summary>
/// 上传文件
/// </summary>
/// <param name="obj"></param>
private async void UploadClickCommandFunc(object obj)
{
if (LocalTreeSelectedItem == null)
{
await MessageBox.ShowAsync("请选择要上传的文件或文件夹");
return;
}
if (LocalTreeSelectedItem.IsBack)
{
return;
}
bool cover = false;
var result = await MessageBox.ShowOverlayAsync("上传过程中可能文件存在,是否覆盖上传", "提示", button: MessageBoxButton.YesNo);
if (result != MessageBoxResult.Yes)
{
cover = false;
}
else
{
cover = true;
}
//上传文件夹
if (LocalTreeSelectedItem.IsDirectory)
{
new Thread(() =>
{
UploadDir(LocalTreeSelectedItem, CurrentRemotePath, cover);
Message = $"文件夹上传完成:{LocalTreeSelectedItem.Name}";
Dispatcher.UIThread.Invoke(() =>
{
RemoteTree = GetRemoteFoldersAndFiles();
});
}).Start();
}
//上传文件
else
{
new Thread(() =>
{
try
{
//判断远端是否存在文件,是否覆盖
bool isExist = ftp.IsFileExist(CurrentRemotePath, LocalTreeSelectedItem.Name);
if (isExist && !cover)
{
return;
}
Message = $"准备上传:{LocalTreeSelectedItem.Path}";
ftp.UploadFile(LocalTreeSelectedItem.Path, CurrentRemotePath + LocalTreeSelectedItem.Name);
Message = $"上传完成:{LocalTreeSelectedItem.Path}";
}
catch (Exception ex)
{
Message = $"上传失败:{LocalTreeSelectedItem.Path}";
}
Dispatcher.UIThread.Invoke(() =>
{
RemoteTree = GetRemoteFoldersAndFiles();
});
}).Start();
}
}
/// <summary>
/// 下载文件
/// </summary>
/// <param name="obj"></param>
private async void DownloadClickCommandFunc(object obj)
{
if (RemoteTreeSelectedItem == null)
{
await MessageBox.ShowAsync("请选择要下载的文件或文件夹");
return;
}
if (CurrentLocalPath == "")
{
await MessageBox.ShowAsync("请选择本地路径");
return;
}
if (RemoteTreeSelectedItem.IsBack)
{
return;
}
bool cover = false;
var result = await MessageBox.ShowOverlayAsync("下载过程中可能文件存在,是否覆盖下载", "提示", button: MessageBoxButton.YesNo);
if (result != MessageBoxResult.Yes)
{
cover = false;
}
else
{
cover = true;
}
//下载文件夹
if (RemoteTreeSelectedItem.IsDirectory)
{
new Thread(() =>
{
DownloadDir(RemoteTreeSelectedItem, CurrentLocalPath, cover);
Message = $"文件夹下载完成:{RemoteTreeSelectedItem.Name}";
Dispatcher.UIThread.Invoke(() =>
{
LocalTree = GetFoldersAndFiles();
});
}).Start();
}
//下载文件
else
{
new Thread(() =>
{
try
{
if (File.Exists(CurrentLocalPath + "/" + RemoteTreeSelectedItem.Name) && !cover)
{
return;
}
Message = $"准备下载:{RemoteTreeSelectedItem.Name}";
ftp.DownloadFile(RemoteTreeSelectedItem.Path, CurrentLocalPath + "/" + RemoteTreeSelectedItem.Name);
Message = $"下载完成:{RemoteTreeSelectedItem.Name}";
}
catch (Exception ex)
{
Message = $"下载失败:{ex.Message}";
}
Dispatcher.UIThread.Invoke(() =>
{
LocalTree = GetFoldersAndFiles();
});
}).Start();
}
}
/// <summary>
/// 删除FTP文件
/// </summary>
/// <param name="obj"></param>
/// <exception cref="NotImplementedException"></exception>
private async void RemoteDeleteClickCommandFunc(object obj)
{
try
{
if (RemoteTreeSelectedItem == null)
{
await MessageBox.ShowAsync("请选择要删除的文件或文件夹");
return;
}
if (RemoteTreeSelectedItem.IsBack)
{
return;
}
var result = await MessageBox.ShowOverlayAsync("是否确定删除", "提示", button: MessageBoxButton.YesNo);
if (result != MessageBoxResult.Yes)
{
return;
}
if (RemoteTreeSelectedItem.IsDirectory)
{
new Thread(() =>
{
try
{
DeleteDirecory(RemoteTreeSelectedItem.Path);
Message = $"删除成功:{RemoteTreeSelectedItem.Path}";
}
catch (Exception ex)
{
Message = $"删除失败:{ex.Message}";
}
Dispatcher.UIThread.Invoke(() =>
{
RemoteTree = GetRemoteFoldersAndFiles();
});
}).Start();
}
else
{
new Thread(() =>
{
Message = $"准备删除:{RemoteTreeSelectedItem.Path}";
try
{
ftp.DeleteFile(RemoteTreeSelectedItem.Path);
Message = $"删除成功:{RemoteTreeSelectedItem.Path}";
}
catch (Exception ex)
{
Message = $"删除失败:{ex.Message}";
}
Dispatcher.UIThread.Invoke(() =>
{
RemoteTree = GetRemoteFoldersAndFiles();
});
}).Start();
}
}
catch (Exception ex)
{
await MessageBox.ShowAsync(ex.Message);
}
}
private void DeleteDirecory(string path)
{
List<FtpFileInfo> list = ftp.GetList(path);
foreach (FtpFileInfo info in list)
{
if (info.IsDirectory)
{
DeleteDirecory(path + info.Name + "/");
}
else
{
Message = $"准备删除:{path + info.Name}";
try
{
ftp.DeleteFile(path + info.Name);
Message = $"删除成功:{path + info.Name}";
}
catch (Exception ex)
{
Message = $"删除失败:{ex.Message}";
}
}
}
ftp.DeleteDirectory(path);
}
/// <summary>
/// 递归调用
/// </summary>
/// <param name="remoteTreeSelectedItem"></param>
/// <param name="currentLocalPath"></param>
/// <exception cref="NotImplementedException"></exception>
private void DownloadDir(MyDir remoteTreeSelectedItem, string currentLocalPath, bool cover)
{
//文件夹是否存在
string localPath = currentLocalPath + "/" + remoteTreeSelectedItem.Name;
if (!Directory.Exists(localPath))
{
Directory.CreateDirectory(localPath);
}
List<FtpFileInfo> myDirs = ftp.GetList(remoteTreeSelectedItem.Path);
foreach (FtpFileInfo f in myDirs)
{
if (f.IsDirectory)
{
MyDir dir = new MyDir { IsDirectory = true, Name = f.Name, Path = remoteTreeSelectedItem.Path + f.Name + "/" };
DownloadDir(dir, localPath, cover);
}
else
{
try
{
if (File.Exists(localPath + "/" + f.Name) && !cover)
{
return;
}
Message = $"准备下载:{remoteTreeSelectedItem.Path + f.Name}";
ftp.DownloadFile(remoteTreeSelectedItem.Path + f.Name, localPath + "/" + f.Name);
Message = $"下载完成:{remoteTreeSelectedItem.Path + f.Name}";
}
catch (Exception ex)
{
Message = $"下载失败:{ex.Message}";
}
}
}
}
private void UploadDir(MyDir localTreeSelectedItem, string currentRemotePath, bool cover)
{
//文件夹是否存在
string remotePath = currentRemotePath + localTreeSelectedItem.Name + "/";
if (!ftp.FolderExists(currentRemotePath, localTreeSelectedItem.Name))
{
ftp.CreateFolder(remotePath);
}
string[] dirList = Directory.GetDirectories(localTreeSelectedItem.Path).Select(it => it.Replace("\\", "/")).ToArray();
string[] fileList = Directory.GetFiles(localTreeSelectedItem.Path).Select(it => it.Replace("\\", "/")).ToArray();
foreach (string f in dirList)
{
MyDir dir = new MyDir { IsDirectory = true, Name = System.IO.Path.GetFileName(f), Path = f };
UploadDir(dir, remotePath, cover);
}
foreach (string f in fileList)
{
try
{
bool isExist = ftp.IsFileExist(remotePath + "/", System.IO.Path.GetFileName(f));
if (isExist)
{
continue;
}
Message = $"准备上传:{localTreeSelectedItem.Path + System.IO.Path.GetFileName(f)}";
ftp.UploadFile(localTreeSelectedItem.Path + "/" + System.IO.Path.GetFileName(f), remotePath + "/" + System.IO.Path.GetFileName(f));
Message = $"上传完成:{localTreeSelectedItem.Path + System.IO.Path.GetFileName(f)}";
}
catch (Exception ex)
{
Message = $"上传失败:{ex.Message}";
}
}
}
private void RemoteRenameClickCommandFunc(object obj)
{
if (RemoteTreeSelectedItem == null)
{
MessageBox.ShowAsync("请选择要重命名的文件或文件夹");
return;
}
if (RemoteTreeSelectedItem.IsBack)
{
return;
}
string newName = Interaction.InputBox("请输入新名字", "", "", 200, 100);
if (newName.IsNullOrEmpty())
{
MessageBox.ShowAsync("请输入新文件名");
return;
}
string path = "";
if (RemoteTreeSelectedItem.IsDirectory)
{
path = CurrentRemotePath;
if (path.EndsWith("/"))
path = path.Substring(0, path.Length - 1);
int index = path.LastIndexOf("/");
if (index == -1)
{
path = "";
}
else
{
path = path.Substring(0, index + 1);
}
path += newName + "/";
}
else
{
path = CurrentRemotePath;
if (path.EndsWith("/"))
path = path.Substring(0, path.Length - 1);
int index = path.LastIndexOf("/");
if (index == -1)
{
path = "";
}
else
{
path = path.Substring(0, index + 1);
}
string ext = System.IO.Path.GetExtension(RemoteTreeSelectedItem.Path);
if (!newName.ToLower().EndsWith(ext.ToLower()))
{
path = path + newName + ext;
}
}
new Thread(() =>
{
try
{
ftp.Rename(RemoteTreeSelectedItem.Path, path);
Dispatcher.UIThread.Invoke(() =>
{
RemoteTree = GetRemoteFoldersAndFiles();
});
}
catch (Exception ex)
{
Message = $"重命名失败:{ex.Message}";
}
}).Start();
}
}
public class MyDir
{
public string Path { get; set; }
public string Name { get; set; }
public bool IsDirectory { get; set; }
public bool IsBack { get; set; }
}
}