using HeBianGu.Base.WpfBase; using HeBianGu.Service.Mvc; using Hopetry.Services; using Microsoft.Win32; using Minio.DataModel.Args; using Minio.DataModel; using System; using System.Collections.ObjectModel; using System.Windows; using System.Windows.Input; using System.Windows.Threading; using Minio; using Microsoft.Extensions.Configuration; using Hopetry.ViewModel.Send; using System.IO; using System.Security.AccessControl; using System.Diagnostics; using Microsoft.WindowsAPICodePack.Dialogs; namespace HeBianGu.App.Disk { [ViewModel("Loyout")] internal class LoyoutViewModel : MvcViewModelBase { private string _path; /// 说明 public string Path { get { return _path; } set { _path = value; RaisePropertyChanged("Path"); } } private string _nearPath; /// 说明 public string NearPath { get { return _nearPath; } set { _nearPath = value; RaisePropertyChanged("NearPath"); } } private string _sharePath; /// 说明 public string SharePath { get { return _sharePath; } set { _sharePath = value; RaisePropertyChanged("SharePath"); } } protected override void Init() { Path = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); NearPath = Environment.GetFolderPath(Environment.SpecialFolder.Recent); SharePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); // LinkActions.Add(new LinkAction() { Action = "Near", Controller = "Loyout", DisplayName = "最近使用", Logo = "\xe6f3" }); LinkActions.Add(new LinkAction() { Action = "Explorer", Controller = "Loyout", DisplayName = "全部文件", Logo = "" }); // LinkActions.Add(new LinkAction() { Action = "Image", Controller = "Loyout", DisplayName = " 图片", Logo = "" }); // LinkActions.Add(new LinkAction() { Action = "Video", Controller = "Loyout", DisplayName = " 视频", Logo = "" }); // LinkActions.Add(new LinkAction() { Action = "Document", Controller = "Loyout", DisplayName = " 文档", Logo = "" }); // LinkActions.Add(new LinkAction() { Action = "Music", Controller = "Loyout", DisplayName = " 音乐", Logo = "" }); // LinkActions.Add(new LinkAction() { Action = "Explorer", Controller = "Loyout", DisplayName = " 种子", Logo = "" }); //LinkActions.Add(new LinkAction() { Action = "Recent", Controller = "Loyout", DisplayName = " 其他", Logo = "" }); // LinkActions.Add(new LinkAction() { Action = "Space", Controller = "Loyout", DisplayName = "隐藏空间", Logo = "\xe613" }); //LinkActions.Add(new LinkAction() { Action = "Share", Controller = "Loyout", DisplayName = "我的分享", Logo = "\xe764" }); // LinkActions.Add(new LinkAction() { Action = "Near", Controller = "Loyout", DisplayName = "回收站", Logo = "\xe618" }); Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => { SelectLink = LinkActions[0]; })); } protected override void Loaded(string args) { } #region 文件上传 //private SendViewModel _sendViewModel; //private IConfiguration config; //public ICommand UploadCommand { get; } //public ICommand UploadCommand1 { get; } //public LoyoutViewModel(SendViewModel sendViewModel, IConfiguration _config) //{ // _sendViewModel = sendViewModel; // config = _config; // UploadCommand = new AsyncRelayCommand(async () => await UploadFile()); // UploadCommand1 = new AsyncRelayCommand(async () => await UploadFile1()); //} //private SemaphoreSlim _semaphore = new SemaphoreSlim(5); //private async Task UploadFile() //{ // var openFileDialog = new Microsoft.Win32.OpenFileDialog(); // openFileDialog.Multiselect = true; // 可选择多个文件 // openFileDialog.Filter = "All Files (*.*)|*.*"; // //openFileDialog.Multiselect = false; // if (openFileDialog.ShowDialog() == true) // { // foreach (string filePath in openFileDialog.FileNames) // { // UpLoadItems ut = new UpLoadItems(); // ut.Value = System.IO.Path.GetFileName(filePath); // ut.Value3 = "等待上传"; // ut.Value5 = filePath; // ut.Value6 = System.IO.Path.GetFileName(filePath); // FileInfo fileInfo = new FileInfo(filePath); // ut.Double1 = fileInfo.Length; // ut.Double2 = 0.0; // ut.Bool1 = false; // if (fileInfo.Exists) // { // if (fileInfo.Length < 1024 * 1024) // { // ut.Value1 = "0KB/" + Math.Round((double)(fileInfo.Length / 1024), 2).ToString() + "KB"; // } // else // { // ut.Value1 = "0MB/" + Math.Round((double)(fileInfo.Length / (1024 * 1024)), 2).ToString() + "MB"; // } // } // _sendViewModel.UpLoadItems.Add(ut); // } // //更新总进度 // var timer = new System.Timers.Timer(1000); // 每秒更新一次 // timer.Elapsed += (sender, e) => // { // double currentBytes = _sendViewModel.UpLoadItems.Sum(r=>r.Double2); // double totalBytes = _sendViewModel.UpLoadItems.Sum(r => r.Double1); // double speed = Math.Round((currentBytes / totalBytes)*100,0); // KB/s // _sendViewModel.Progress = speed; // }; // timer.Start(); // try // { // // 创建所有上传任务 // var uploadTasks = _sendViewModel.UpLoadItems.Where(item=>item.Bool1==false) // .Select(async item => // { // await _semaphore.WaitAsync(); // 等待信号量 // try // { // await UploadFileToMinIOWithProgress(item); // } // finally // { // _semaphore.Release(); // 释放信号量 // } // }) // .ToList(); // // 等待所有上传任务完成 // await Task.WhenAll(uploadTasks); // } // finally // { // //更新总进度100% // _sendViewModel.Progress = 100; // // 关机 // if (MySetting.Instance.IsOn) // { // Shutdown(); // } // // 停止计时器 // timer.Stop(); // } // } //} //private async Task UploadFileToMinIOWithProgress(UpLoadItems ut) //{ // // 配置 MinIO 客户端 // IMinioClient client = new Minio.MinioClient() // .WithEndpoint("123.132.248.154:9107") // MinIO 服务器地址 // .WithCredentials("KcJPKzOsKfVq20EA4Lyh", "HY7K5EkYpRUphEdINZmAq34tsZD3PMLFTnL85y4N") // 访问密钥和密钥 // .Build(); // try // { // string bucketName = "test"; // string objectName = System.IO.Path.GetFileName(ut.Value5); // //var aa = _sendViewModel.UpLoadItems.Where(r => r.Value == objectName).FirstOrDefault(); // //判断桶是否存在 // var beArgs = new BucketExistsArgs().WithBucket(bucketName); // bool found = await client.BucketExistsAsync(beArgs).ConfigureAwait(false); // if (!found) // { // var mbArgs = new MakeBucketArgs() // .WithBucket(bucketName); // await client.MakeBucketAsync(mbArgs).ConfigureAwait(false); // } // var progress = new Progress(progressReport => // { // // 确保在 UI 线程上更新 Progress // Application.Current.Dispatcher.Invoke(() => // { // //_sendViewModel.Progress = progressReport.Percentage; // ut.Int1 = progressReport.Percentage; // int slashIndex = ut.Value1.IndexOf('/'); // long trans = progressReport.TotalBytesTransferred; // ut.Double2 = trans; // if (trans < 1024 * 1024) // { // ut.Value1 = Math.Round((double)(trans / 1024), 0).ToString() + "KB" + ut.Value1.Substring(slashIndex); // } // else // { // ut.Value1 = Math.Round((double)(trans / (1024 * 1024)), 2).ToString() + "MB" + ut.Value1.Substring(slashIndex); // } // ut.Value3 = "上传中..."; // }); // }); // PutObjectArgs putObjectArgs = new PutObjectArgs() // .WithBucket(bucketName) // .WithObject(ut.Value6) // .WithFileName(ut.Value5) // //.WithContentType("application/octet-stream") // .WithProgress(progress); // // 上传文件并提供进度反馈 // await client.PutObjectAsync(putObjectArgs); // ut.Value3 = "已完成"; // ut.Bool1 = true; // //MessageBox.Show("文件上传成功!"); // } // catch (Exception ex) // { // MessageBox.Show($"上传失败: {ex.Message}"); // } //} ////文件夹上传 //private async Task UploadFile1() //{ // var dialog = new CommonOpenFileDialog // { // IsFolderPicker = true, // Title = "请选择上传文件" // }; // if (dialog.ShowDialog() == CommonFileDialogResult.Ok) // { // string folderPath = dialog.FileName; // var files = Directory.GetFiles(folderPath, "*.*", SearchOption.AllDirectories); // foreach (string filePath in files) // { // UpLoadItems ut = new UpLoadItems(); // ut.Value = System.IO.Path.GetFileName(filePath); // ut.Value3 = "等待上传"; // ut.Value5 = filePath; // ut.Value6= filePath.Substring(folderPath.Length + 1).Replace('\\', '/'); // ; // FileInfo fileInfo = new FileInfo(filePath); // ut.Double1 = fileInfo.Length; // ut.Double2 = 0.0; // if (fileInfo.Exists) // { // if (fileInfo.Length < 1024 * 1024) // { // ut.Value1 = "0KB/" + Math.Round((double)(fileInfo.Length / 1024), 2).ToString() + "KB"; // } // else // { // ut.Value1 = "0MB/" + Math.Round((double)(fileInfo.Length / (1024 * 1024)), 2).ToString() + "MB"; // } // } // _sendViewModel.UpLoadItems.Add(ut); // } // //更新总进度 // var timer = new System.Timers.Timer(1000); // 每秒更新一次 // timer.Elapsed += (sender, e) => // { // double currentBytes = _sendViewModel.UpLoadItems.Sum(r => r.Double2); // double totalBytes = _sendViewModel.UpLoadItems.Sum(r => r.Double1); // double speed = Math.Round((currentBytes / totalBytes) * 100, 0); // KB/s // _sendViewModel.Progress = speed; // }; // timer.Start(); // try // { // // 创建所有上传任务 // var uploadTasks = _sendViewModel.UpLoadItems.Where(item => item.Bool1 == false) // .Select(async item => // { // await _semaphore.WaitAsync(); // 等待信号量 // try // { // await UploadFileToMinIOWithProgress(item); // } // finally // { // _semaphore.Release(); // 释放信号量 // } // }) // .ToList(); // // 等待所有上传任务完成 // await Task.WhenAll(uploadTasks); // } // finally // { // //更新总进度100% // _sendViewModel.Progress = 100; // // 关机 // if (MySetting.Instance.IsOn) // { // Shutdown(); // } // // 停止计时器 // timer.Stop(); // } // } //} //// 关机方法 //private void Shutdown() //{ // try // { // // 使用shutdown命令关机 // Process.Start("shutdown", "/s /t 0"); // } // catch (System.ComponentModel.Win32Exception ex) // { // MessageBox.Show($"关机失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); // } //} #endregion #region 文件上传 private SendViewModel _sendViewModel; private IConfiguration config; private SemaphoreSlim _semaphore = new SemaphoreSlim(5); private System.Timers.Timer _progressTimer; private bool _isTimerRunning = false; private object _timerLock = new object(); private bool _isUploading = false; // 新增:标记是否有上传任务正在运行 private Task _currentUploadTask = null; // 新增:当前上传任务 private CancellationTokenSource _uploadCancellation = new CancellationTokenSource(); public ICommand UploadCommand { get; } public ICommand UploadCommand1 { get; } public LoyoutViewModel(SendViewModel sendViewModel) { _sendViewModel = sendViewModel; UploadCommand = new AsyncRelayCommand(async () => await UploadFile()); UploadCommand1 = new AsyncRelayCommand(async () => await UploadFile1()); // 初始化Timer _progressTimer = new System.Timers.Timer(1000); _progressTimer.Elapsed += UpdateProgress; } private void UpdateProgress(object sender, System.Timers.ElapsedEventArgs e) { lock (_timerLock) { if (_sendViewModel.UpLoadItems.Count == 0) return; double currentBytes = _sendViewModel.UpLoadItems.Sum(r => r.Double2); double totalBytes = _sendViewModel.UpLoadItems.Sum(r => r.Double1); double progress = Math.Round((currentBytes / totalBytes) * 100, 0); Application.Current.Dispatcher.Invoke(() => { _sendViewModel.Progress = progress; }); } } private void StartProgressTimer() { lock (_timerLock) { if (!_isTimerRunning) { _progressTimer.Start(); _isTimerRunning = true; } } } private void StopProgressTimer() { lock (_timerLock) { if (_isTimerRunning) { _progressTimer.Stop(); _isTimerRunning = false; } } } private async Task UploadFile() { var openFileDialog = new Microsoft.Win32.OpenFileDialog { Multiselect = true, Filter = "All Files (*.*)|*.*" }; if (openFileDialog.ShowDialog() == true) { // 过滤掉已经存在的文件 var newFiles = openFileDialog.FileNames .Where(filePath => !_sendViewModel.UpLoadItems.Any(item => item.Value5.Equals(filePath, StringComparison.OrdinalIgnoreCase))) .ToList(); if (newFiles.Count == 0) { MessageBox.Show("没有新文件需要上传或文件已在上传队列中"); return; } foreach (string filePath in newFiles) { var ut = CreateUploadItem(filePath, System.IO.Path.GetFileName(filePath)); _sendViewModel.UpLoadItems.Add(ut); } MessageBox.Show("传输列表中可查看进度"); // 如果没有上传任务在运行,则启动上传 if (!_isUploading) { await ProcessUploadTasks(); } } } private async Task UploadFile1() { var dialog = new CommonOpenFileDialog { IsFolderPicker = true, Title = "请选择上传文件" }; if (dialog.ShowDialog() == CommonFileDialogResult.Ok) { string folderPath = dialog.FileName; string folderName = new DirectoryInfo(folderPath).Name; // 获取选中的文件夹名称 var files = Directory.GetFiles(folderPath, "*.*", SearchOption.AllDirectories) .Where(filePath => !_sendViewModel.UpLoadItems.Any(item => item.Value5.Equals(filePath, StringComparison.OrdinalIgnoreCase))) .ToList(); if (files.Count == 0) { MessageBox.Show("没有新文件需要上传或文件已在上传队列中"); return; } foreach (string filePath in files) { string relativePath = folderName + "/" + filePath.Substring(folderPath.Length + 1).Replace('\\', '/'); var ut = CreateUploadItem(filePath, relativePath); _sendViewModel.UpLoadItems.Add(ut); } MessageBox.Show("传输列表中可查看进度"); // 如果没有上传任务在运行,则启动上传 if (!_isUploading) { await ProcessUploadTasks(); } } } private UpLoadItems CreateUploadItem(string filePath, string objectName) { FileInfo fileInfo = new FileInfo(filePath); string sizeText = fileInfo.Length < 1024 * 1024 ? $"{Math.Ceiling((decimal)fileInfo.Length / 1024)}KB" : $"{Math.Ceiling((decimal)fileInfo.Length / (1024 * 1024))}MB"; return new UpLoadItems { Value = System.IO.Path.GetFileName(filePath), Value3 = "等待上传", Value5 = filePath, Value6 = objectName, Double1 = fileInfo.Length, Double2 = 0.0, Bool1 = false, Value1 = $"0{(fileInfo.Length < 1024 * 1024 ? "KB" : "MB")}/{sizeText}" }; } private async Task ProcessUploadTasks() { _isUploading = true; StartProgressTimer(); try { while (true) { // 获取所有未完成的上传项 var pendingItems = _sendViewModel.UpLoadItems .Where(item => !item.Bool1) .ToList(); if (!pendingItems.Any()) break; // 没有待上传文件,退出循环 // 创建并运行上传任务 _currentUploadTask = Task.WhenAll(pendingItems.Select(async item => { await _semaphore.WaitAsync(_uploadCancellation.Token); try { await UploadFileToMinIOWithProgress(item); } finally { _semaphore.Release(); } })); await _currentUploadTask; } } catch (OperationCanceledException) { // 上传被取消 } finally { StopProgressTimer(); Application.Current.Dispatcher.Invoke(() => { _sendViewModel.Progress = 100; }); _isUploading = false; if (MySetting.Instance.IsOn && !_sendViewModel.UpLoadItems.Any(item => !item.Bool1)) { Shutdown(); } } } private async Task UploadFileToMinIOWithProgress(UpLoadItems ut) { ut.Bool1 = true; var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("global.json", optional: false, reloadOnChange: true); // 构建配置 var config = builder.Build(); // 从配置获取MinIO设置更安全 IMinioClient client = new Minio.MinioClient() .WithEndpoint(config["Minio:Endpoint"]) .WithCredentials(config["Minio:AccessKey"], config["Minio:SecretKey"]) .Build(); try { string bucketName = config["Minio:BucketName"]; // 确保桶存在 var beArgs = new BucketExistsArgs().WithBucket(bucketName); bool found = await client.BucketExistsAsync(beArgs).ConfigureAwait(false); if (!found) { var mbArgs = new MakeBucketArgs().WithBucket(bucketName); await client.MakeBucketAsync(mbArgs).ConfigureAwait(false); } var progress = new Progress(progressReport => { Application.Current.Dispatcher.Invoke(() => { ut.Int1 = progressReport.Percentage; long trans = progressReport.TotalBytesTransferred; ut.Double2 = trans; int slashIndex = ut.Value1.IndexOf('/'); string sizePart = ut.Value1.Substring(slashIndex); string transferredPart = trans < 1024 * 1024 ? $"{Math.Ceiling((decimal)trans / 1024)}KB" : $"{Math.Ceiling((decimal)trans / (1024 * 1024))}MB"; ut.Value1 = $"{transferredPart}{sizePart}"; if (progressReport.Percentage == 100) { ut.Value3 = "已完成"; //_sendViewModel.UpLoadItems.Remove(ut); //_sendViewModel.CompleteItems.Add(ut); } else { ut.Value3 = "上传中..."; } }); }); var putObjectArgs = new PutObjectArgs() .WithBucket(bucketName) .WithObject(ut.Value6) .WithFileName(ut.Value5) .WithProgress(progress); await client.PutObjectAsync(putObjectArgs); } catch (Exception ex) { Application.Current.Dispatcher.Invoke(() => { ut.Value3 = $"上传失败: {ex.Message}"; }); } } private void Shutdown() { try { Process.Start("shutdown", "/s /t 0"); } catch (System.ComponentModel.Win32Exception ex) { MessageBox.Show($"关机失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } #endregion } internal class DataFileViewModel : ObservableSourceViewModel { protected override void Init() { base.Init(); } } }