2025-06-04 17:20:25 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.ObjectModel;
|
2025-03-20 16:08:11 +08:00
|
|
|
|
using System.ComponentModel;
|
2025-06-04 17:20:25 +08:00
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Net.Http;
|
|
|
|
|
|
using System.Security.AccessControl;
|
2025-03-17 10:58:59 +08:00
|
|
|
|
using System.Windows;
|
2025-06-04 17:20:25 +08:00
|
|
|
|
using System.Windows.Documents;
|
|
|
|
|
|
using System.Windows.Input;
|
2025-03-17 10:58:59 +08:00
|
|
|
|
using System.Windows.Threading;
|
2025-06-04 17:20:25 +08:00
|
|
|
|
using HeBianGu.Base.WpfBase;
|
2025-04-18 16:38:37 +08:00
|
|
|
|
using HeBianGu.General.WpfControlLib;
|
2025-04-26 10:53:46 +08:00
|
|
|
|
using HeBianGu.Service.Mvc;
|
2025-06-04 17:20:25 +08:00
|
|
|
|
using Hopetry.Provider;
|
|
|
|
|
|
using Hopetry.Provider.Behaviors;
|
|
|
|
|
|
using Hopetry.Services;
|
2025-04-26 10:53:46 +08:00
|
|
|
|
using Hopetry.ViewModel.Send;
|
2025-06-04 17:20:25 +08:00
|
|
|
|
using Microsoft.Extensions.Configuration;
|
|
|
|
|
|
using Minio.DataModel.Args;
|
|
|
|
|
|
using Minio.DataModel;
|
|
|
|
|
|
using Minio;
|
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
using System.Timers;
|
2025-03-17 10:58:59 +08:00
|
|
|
|
|
|
|
|
|
|
namespace HeBianGu.App.Disk
|
|
|
|
|
|
{
|
|
|
|
|
|
[ViewModel("Send")]
|
|
|
|
|
|
internal class SendViewModel : MvcViewModelBase
|
|
|
|
|
|
{
|
2025-04-18 16:38:37 +08:00
|
|
|
|
private LinkAction _uploadingAction; //正在上传
|
|
|
|
|
|
private LinkAction _completeAction; //上传完成
|
2025-04-26 10:53:46 +08:00
|
|
|
|
public LinkAction DownLinkAction;
|
2025-06-04 17:20:25 +08:00
|
|
|
|
public LinkAction _waituploadAction;
|
|
|
|
|
|
private readonly FileUploadService _uploadService;
|
|
|
|
|
|
public ICommand WaitUpLoadCommand { get; }
|
|
|
|
|
|
public ICommand DeleteWaitUpLoadCommand { get; }
|
|
|
|
|
|
public bool _isUploading = false;
|
2025-04-18 16:38:37 +08:00
|
|
|
|
|
2025-06-04 17:20:25 +08:00
|
|
|
|
public string CurrentMinIOPath;
|
|
|
|
|
|
public SendViewModel()
|
|
|
|
|
|
{
|
|
|
|
|
|
_uploadService = new FileUploadService();
|
|
|
|
|
|
// 初始化Timer
|
|
|
|
|
|
_progressTimer = new System.Timers.Timer(1000);
|
|
|
|
|
|
_progressTimer.Elapsed += UpdateProgress;
|
|
|
|
|
|
_heartbeatTimer = new System.Timers.Timer(30_000);
|
|
|
|
|
|
//_heartbeatTimer.Elapsed += async (s, e) => await SendHeartbeatAsync();
|
|
|
|
|
|
DeleteWaitUpLoadCommand = new AsyncRelayCommand(async () => await DeleteFile());
|
|
|
|
|
|
WaitUpLoadCommand = new AsyncRelayCommand(async () => await UploadWaitItems());
|
|
|
|
|
|
systemInfo = SystemInfoCollector.Collect();
|
|
|
|
|
|
//加载待上传列表
|
|
|
|
|
|
GetWaitUploadItems();
|
|
|
|
|
|
//加载上传完成列表
|
|
|
|
|
|
GetCompletedFiles();
|
|
|
|
|
|
}
|
2025-04-18 14:04:28 +08:00
|
|
|
|
protected override void Init()
|
2025-03-17 10:58:59 +08:00
|
|
|
|
{
|
2025-04-18 16:38:37 +08:00
|
|
|
|
ITransitionWipe wipe = new CircleWipe();
|
2025-04-26 10:53:46 +08:00
|
|
|
|
|
|
|
|
|
|
DownLinkAction = new LinkAction()
|
2025-06-04 17:20:25 +08:00
|
|
|
|
{ Action = "Down", Controller = "Send", DisplayName = "下载 0", Logo = "\xe891", TransitionWipe = wipe };
|
2025-04-26 10:53:46 +08:00
|
|
|
|
LinkActions.Add(DownLinkAction);
|
2025-04-15 09:14:45 +08:00
|
|
|
|
// 正在上传
|
|
|
|
|
|
_uploadingAction = new LinkAction()
|
|
|
|
|
|
{
|
|
|
|
|
|
Action = "UpLoad",
|
|
|
|
|
|
Controller = "Send",
|
|
|
|
|
|
DisplayName = "正在上传",
|
2025-06-04 17:20:25 +08:00
|
|
|
|
Logo = "\xe6f3",
|
|
|
|
|
|
TransitionWipe = wipe
|
2025-04-15 09:14:45 +08:00
|
|
|
|
};
|
|
|
|
|
|
LinkActions.Add(_uploadingAction);
|
|
|
|
|
|
|
|
|
|
|
|
_completeAction = new LinkAction()
|
|
|
|
|
|
{
|
|
|
|
|
|
Action = "CompleteUpload",
|
|
|
|
|
|
Controller = "Send",
|
|
|
|
|
|
DisplayName = "上传完成",
|
2025-06-04 17:20:25 +08:00
|
|
|
|
Logo = "\xe613",
|
|
|
|
|
|
TransitionWipe = wipe
|
2025-04-15 09:14:45 +08:00
|
|
|
|
};
|
|
|
|
|
|
LinkActions.Add(_completeAction);
|
2025-06-04 17:20:25 +08:00
|
|
|
|
|
|
|
|
|
|
_waituploadAction = new LinkAction()
|
|
|
|
|
|
{
|
|
|
|
|
|
Action = "WaitUpload",
|
|
|
|
|
|
Controller = "Send",
|
|
|
|
|
|
DisplayName = "待上传",
|
|
|
|
|
|
Logo = "\xe613",
|
|
|
|
|
|
TransitionWipe = wipe
|
|
|
|
|
|
};
|
|
|
|
|
|
LinkActions.Add(_waituploadAction);
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-04-18 16:38:37 +08:00
|
|
|
|
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Loaded,
|
|
|
|
|
|
new Action(() => { SelectLink = LinkActions[0]; }));
|
2025-04-18 16:23:55 +08:00
|
|
|
|
UpLoadItems.CollectionChanged += (s, e) => { UpdateUploadingItems(); };
|
2025-06-04 17:20:25 +08:00
|
|
|
|
|
2025-03-17 10:58:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void Loaded(string args)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
2025-03-20 16:08:11 +08:00
|
|
|
|
|
|
|
|
|
|
#region 文件上传
|
2025-04-18 16:38:37 +08:00
|
|
|
|
|
2025-06-04 17:20:25 +08:00
|
|
|
|
#region 参数
|
|
|
|
|
|
|
2025-04-07 11:30:57 +08:00
|
|
|
|
//上传文件总数
|
2025-03-24 10:09:10 +08:00
|
|
|
|
private ObservableCollection<UpLoadItems> _upLoadItems = new ObservableCollection<UpLoadItems>();
|
2025-04-18 16:38:37 +08:00
|
|
|
|
|
2025-03-24 10:09:10 +08:00
|
|
|
|
/// <summary> 说明 </summary>
|
|
|
|
|
|
public ObservableCollection<UpLoadItems> UpLoadItems
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return _upLoadItems; }
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
_upLoadItems = value;
|
2025-04-07 11:30:57 +08:00
|
|
|
|
//UpdateUploadingItems();
|
2025-03-24 10:09:10 +08:00
|
|
|
|
RaisePropertyChanged("UpLoadItems");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-07 11:30:57 +08:00
|
|
|
|
//已上传完成文件
|
2025-03-27 09:32:04 +08:00
|
|
|
|
private ObservableCollection<UpLoadItems> _completeItems = new ObservableCollection<UpLoadItems>();
|
2025-04-18 16:38:37 +08:00
|
|
|
|
|
2025-03-27 09:32:04 +08:00
|
|
|
|
public ObservableCollection<UpLoadItems> CompleteItems
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return _completeItems; }
|
2025-04-07 11:30:57 +08:00
|
|
|
|
private set
|
2025-03-27 09:32:04 +08:00
|
|
|
|
{
|
|
|
|
|
|
_completeItems = value;
|
|
|
|
|
|
RaisePropertyChanged("CompleteItems");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-04 17:20:25 +08:00
|
|
|
|
//待上传文件
|
|
|
|
|
|
private ObservableCollection<UpLoadItems> _waitUpLoadItems = new ObservableCollection<UpLoadItems>();
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary> 说明 </summary>
|
|
|
|
|
|
public ObservableCollection<UpLoadItems> WaitUpLoadItems
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return _waitUpLoadItems; }
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
_waitUpLoadItems = value;
|
|
|
|
|
|
RaisePropertyChanged("WaitUpLoadItems");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-07 11:30:57 +08:00
|
|
|
|
|
2025-07-05 13:59:04 +08:00
|
|
|
|
private bool? _isAllSelected;
|
|
|
|
|
|
public bool? IsAllSelected
|
|
|
|
|
|
{
|
|
|
|
|
|
get => _isAllSelected;
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
_isAllSelected = value;
|
|
|
|
|
|
// 全选/取消全选逻辑
|
|
|
|
|
|
if (value.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var item in WaitUpLoadItems)
|
|
|
|
|
|
{
|
|
|
|
|
|
item.Bool1 = value.Value;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-07 11:30:57 +08:00
|
|
|
|
// 只读属性,返回过滤后的集合(动态计算)
|
|
|
|
|
|
private ObservableCollection<UpLoadItems> _uploadingItems = new ObservableCollection<UpLoadItems>();
|
2025-04-18 16:38:37 +08:00
|
|
|
|
|
2025-04-07 11:30:57 +08:00
|
|
|
|
public ObservableCollection<UpLoadItems> UploadingItems
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return _uploadingItems; }
|
|
|
|
|
|
private set
|
|
|
|
|
|
{
|
|
|
|
|
|
_uploadingItems = value;
|
|
|
|
|
|
RaisePropertyChanged("UploadingItems");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 在 UpLoadItems 变化时更新 UploadingItems
|
|
|
|
|
|
public void UpdateUploadingItems()
|
|
|
|
|
|
{
|
|
|
|
|
|
UploadingItems = new ObservableCollection<UpLoadItems>(
|
|
|
|
|
|
UpLoadItems?.Where(item => item.Value3 != "已完成") ?? Enumerable.Empty<UpLoadItems>()
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//文件上传进度
|
2025-03-20 16:08:11 +08:00
|
|
|
|
private double _progress;
|
|
|
|
|
|
|
|
|
|
|
|
public double Progress
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return _progress; }
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_progress != value)
|
|
|
|
|
|
{
|
|
|
|
|
|
_progress = value;
|
2025-04-18 16:38:37 +08:00
|
|
|
|
RaisePropertyChanged("Progress");
|
2025-03-20 16:08:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-07 11:30:57 +08:00
|
|
|
|
|
|
|
|
|
|
//上传文件个数
|
|
|
|
|
|
private string _filecount;
|
|
|
|
|
|
|
|
|
|
|
|
public string FileCount
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return _filecount; }
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_filecount != value)
|
|
|
|
|
|
{
|
|
|
|
|
|
_filecount = value;
|
|
|
|
|
|
RaisePropertyChanged("FileCount");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-18 16:38:37 +08:00
|
|
|
|
|
2025-04-15 09:14:45 +08:00
|
|
|
|
//上传完成文件个数
|
|
|
|
|
|
private int _uploadingcount;
|
|
|
|
|
|
|
|
|
|
|
|
public int UploadingCount
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return _uploadingcount; }
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_uploadingcount != value)
|
2025-04-18 16:38:37 +08:00
|
|
|
|
{
|
2025-04-15 09:14:45 +08:00
|
|
|
|
_uploadingcount = value;
|
|
|
|
|
|
_uploadingAction.FullName = "(" + _uploadingcount + ")";
|
|
|
|
|
|
RaisePropertyChanged("UploadingCount");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-18 16:38:37 +08:00
|
|
|
|
|
2025-04-15 09:14:45 +08:00
|
|
|
|
//上传文件个数
|
|
|
|
|
|
private int _completecount;
|
|
|
|
|
|
|
|
|
|
|
|
public int CompleteCount
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return _completecount; }
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_completecount != value)
|
|
|
|
|
|
{
|
|
|
|
|
|
_completecount = value;
|
2025-04-18 16:38:37 +08:00
|
|
|
|
_completeAction.FullName = "(" + _completecount + ")";
|
2025-04-15 09:14:45 +08:00
|
|
|
|
RaisePropertyChanged("CompleteCount");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-18 16:38:37 +08:00
|
|
|
|
|
2025-06-04 17:20:25 +08:00
|
|
|
|
//等待上传文件个数
|
|
|
|
|
|
private int _waitcount;
|
|
|
|
|
|
|
|
|
|
|
|
public int WaitCount
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return _waitcount; }
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_waitcount != value)
|
|
|
|
|
|
{
|
|
|
|
|
|
_waitcount = value;
|
|
|
|
|
|
_waituploadAction.FullName = "(" + _waitcount + ")";
|
|
|
|
|
|
RaisePropertyChanged("WaitCount");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region PropertyChanged
|
2025-03-20 16:08:11 +08:00
|
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
|
|
|
|
|
|
|
|
|
|
protected void OnPropertyChanged(string propertyName)
|
|
|
|
|
|
{
|
|
|
|
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
|
|
|
}
|
2025-06-04 17:20:25 +08:00
|
|
|
|
#endregion
|
2025-04-18 16:38:37 +08:00
|
|
|
|
|
2025-03-20 16:08:11 +08:00
|
|
|
|
#endregion
|
2025-06-04 17:20:25 +08:00
|
|
|
|
|
|
|
|
|
|
#region 删除等待上传文件
|
|
|
|
|
|
private async Task DeleteFile()
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
var items = WaitUpLoadItems.Where(r => r.Bool1 == true).ToList();
|
|
|
|
|
|
if (items == null || !items.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
await MessageProxy.Messager.ShowResult("请先选择要删除的项目");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var message = $"确定要删除选中的 {items.Count} 个项目吗?";
|
|
|
|
|
|
var result = MessageBox.Show(message, "确认删除", MessageBoxButton.YesNo);
|
|
|
|
|
|
|
|
|
|
|
|
if (result == MessageBoxResult.Yes)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<string> list = new List<string>();
|
|
|
|
|
|
list=items.Select(r => r.Value4).ToList();
|
|
|
|
|
|
var flag= _uploadService.DeleteFiles(list);
|
|
|
|
|
|
WaitUpLoadItems.RemoveAll(r=>r.Bool1==true);
|
|
|
|
|
|
WaitCount= WaitUpLoadItems.Count;
|
|
|
|
|
|
if (flag == true)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show($"已成功删除 {items.Count} 个项目");
|
2025-07-05 13:59:04 +08:00
|
|
|
|
IsAllSelected = false;
|
2025-06-04 17:20:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show($"删除失败");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show($"删除失败: {ex.Message}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 上传待上传文件
|
|
|
|
|
|
public async Task UploadWaitItems()
|
|
|
|
|
|
{
|
|
|
|
|
|
var items = WaitUpLoadItems.Where(r => r.Bool1 == true).ToList();
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var item in items)
|
|
|
|
|
|
{
|
|
|
|
|
|
FileInfo fileInfo = new FileInfo(item.Value5);
|
|
|
|
|
|
string sizeText = fileInfo.Length < 1024 * 1024
|
|
|
|
|
|
? $"{Math.Ceiling((decimal)fileInfo.Length / 1024)}KB"
|
|
|
|
|
|
: $"{Math.Ceiling((decimal)fileInfo.Length / (1024 * 1024))}MB";
|
|
|
|
|
|
UpLoadItems ut = new UpLoadItems();
|
|
|
|
|
|
ut.Value = item.Value;
|
|
|
|
|
|
ut.Value3 = "等待上传";
|
|
|
|
|
|
ut.Value4 = item.Value4; //唯一标识,与数据库一致
|
|
|
|
|
|
ut.Value5 = item.Value5; //文件名称
|
|
|
|
|
|
ut.Value6 = item.Value6; //文件地址
|
|
|
|
|
|
ut.Double1 = fileInfo.Length;
|
|
|
|
|
|
ut.Double2 = 0.0;
|
|
|
|
|
|
ut.Bool1 = false;
|
|
|
|
|
|
ut.Value1 = $"0{(fileInfo.Length < 1024 * 1024 ? "KB" : "MB")}/{sizeText}";
|
|
|
|
|
|
UpLoadItems.Add(ut);
|
|
|
|
|
|
}
|
|
|
|
|
|
_uploadCount = UpLoadItems.Count;
|
|
|
|
|
|
_completeCount = UpLoadItems.Where(r => r.Value3 == "已完成").Count();
|
|
|
|
|
|
FileCount = _completeCount + "/" + _uploadCount;
|
|
|
|
|
|
UploadingCount = UploadingItems.Count;
|
|
|
|
|
|
CompleteCount = CompleteItems.Count;
|
|
|
|
|
|
MessageBox.Show("正在上传列表中可查看进度");
|
|
|
|
|
|
WaitUpLoadItems.RemoveAll(r => r.Bool1 == true);
|
2025-07-05 13:59:04 +08:00
|
|
|
|
IsAllSelected = false;
|
2025-06-04 17:20:25 +08:00
|
|
|
|
WaitCount = WaitUpLoadItems.Count;
|
|
|
|
|
|
// 如果没有上传任务在运行,则启动上传
|
|
|
|
|
|
if (!_isUploading)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
await ProcessUploadTasks();
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("上传失败");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show("文件丢失");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 获取等待上传列表
|
|
|
|
|
|
public void GetWaitUploadItems()
|
|
|
|
|
|
{
|
|
|
|
|
|
var waitlist = _uploadService.GetAllFiles().Where(r => r.IsComplete == false).ToList();
|
|
|
|
|
|
ObservableCollection<UpLoadItems> up = new ObservableCollection<UpLoadItems>();
|
|
|
|
|
|
if (_isUploading == false)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var file in waitlist)
|
|
|
|
|
|
{
|
|
|
|
|
|
UpLoadItems upLoadItems = new UpLoadItems();
|
|
|
|
|
|
upLoadItems.Value = file.FileName;
|
|
|
|
|
|
upLoadItems.Value4 = file.Id;
|
|
|
|
|
|
upLoadItems.Value5 = file.FilePath;
|
|
|
|
|
|
upLoadItems.Value1 = file.FileSizeText;
|
|
|
|
|
|
upLoadItems.Value6 = file.FileName;
|
|
|
|
|
|
upLoadItems.Value7 = file.CreateTime.ToString("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
|
upLoadItems.Bool1 = false;
|
|
|
|
|
|
up.Add(upLoadItems);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
WaitUpLoadItems.Clear();
|
|
|
|
|
|
WaitUpLoadItems.AddRange(up);
|
|
|
|
|
|
WaitCount = up.Count;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 加载上传完成列表
|
|
|
|
|
|
//加载初始完成文件
|
|
|
|
|
|
public void GetCompletedFiles()
|
|
|
|
|
|
{
|
|
|
|
|
|
var files = _uploadService.GetAllFiles().Where(r => r.IsComplete == true).ToList();
|
|
|
|
|
|
ObservableCollection<UpLoadItems> up = new ObservableCollection<UpLoadItems>();
|
|
|
|
|
|
foreach (var file in files)
|
|
|
|
|
|
{
|
|
|
|
|
|
UpLoadItems upLoadItems = new UpLoadItems();
|
|
|
|
|
|
upLoadItems.Value = file.FileName;
|
|
|
|
|
|
upLoadItems.Value4 = file.Id;
|
|
|
|
|
|
upLoadItems.Value5 = file.FilePath;
|
|
|
|
|
|
upLoadItems.Value1 = file.FileSizeText;
|
|
|
|
|
|
upLoadItems.Value6 = file.FileName;
|
|
|
|
|
|
upLoadItems.Value7 = file.CompleteTime.ToString("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
|
up.Add(upLoadItems);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CompleteItems.Clear();
|
|
|
|
|
|
CompleteItems.AddRange(up);
|
|
|
|
|
|
regionCount = up.Count;
|
|
|
|
|
|
CompleteCount = regionCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 上传
|
|
|
|
|
|
//private SendViewModel _sendViewModel;
|
|
|
|
|
|
private SemaphoreSlim _semaphore = new SemaphoreSlim(5);
|
|
|
|
|
|
private System.Timers.Timer _progressTimer;
|
|
|
|
|
|
private System.Timers.Timer _heartbeatTimer;
|
|
|
|
|
|
private bool _isTimerRunning = false;
|
|
|
|
|
|
private object _timerLock = new object();
|
|
|
|
|
|
private Task _currentUploadTask = null; // 新增:当前上传任务
|
|
|
|
|
|
private CancellationTokenSource _uploadCancellation = new CancellationTokenSource();
|
|
|
|
|
|
public int _uploadCount = 0;
|
|
|
|
|
|
private int _completeCount = 0;
|
|
|
|
|
|
private int regionCount = 0;
|
|
|
|
|
|
private ExplorerMinIOBehavior _explorerBehavior;
|
|
|
|
|
|
private Hopetry.Provider.SystemInfo systemInfo;
|
|
|
|
|
|
// 配置Redis连接
|
|
|
|
|
|
//private RedisService redis = new RedisService("175.27.168.120:6050,password=HopetryRedis1406,connectRetry=3");
|
|
|
|
|
|
#region 更新总进度条 每隔1s更新一次
|
|
|
|
|
|
|
|
|
|
|
|
private void UpdateProgress(object sender, ElapsedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (UpLoadItems.Count == 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
double currentBytes = UpLoadItems.Sum(r => r.Double2);
|
|
|
|
|
|
double totalBytes = UpLoadItems.Sum(r => r.Double1);
|
|
|
|
|
|
double progress = Math.Round((currentBytes / totalBytes) * 100, 2);
|
|
|
|
|
|
|
|
|
|
|
|
Application.Current.Dispatcher.Invoke(() => { Progress = progress; });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//上传redis心跳检测
|
|
|
|
|
|
//private async Task SendHeartbeatAsync()
|
|
|
|
|
|
//{
|
|
|
|
|
|
// try
|
|
|
|
|
|
// {
|
|
|
|
|
|
// // 上报心跳并更新客户端信息
|
|
|
|
|
|
// //await redis.StoreClientInfoAsync(systemInfo);
|
|
|
|
|
|
// await redis.UpdateClientHeartbeatAsync(systemInfo.MachineId);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// catch (Exception ex)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// // 处理网络异常等
|
|
|
|
|
|
// Debug.WriteLine($"心跳上报失败: {ex.Message}");
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
private void StartProgressTimer()
|
|
|
|
|
|
{
|
|
|
|
|
|
lock (_timerLock)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!_isTimerRunning)
|
|
|
|
|
|
{
|
|
|
|
|
|
_progressTimer.Start();
|
|
|
|
|
|
_heartbeatTimer.Start();
|
|
|
|
|
|
_isTimerRunning = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void StopProgressTimer()
|
|
|
|
|
|
{
|
|
|
|
|
|
lock (_timerLock)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_isTimerRunning)
|
|
|
|
|
|
{
|
|
|
|
|
|
_progressTimer.Stop();
|
|
|
|
|
|
_heartbeatTimer.Stop();
|
|
|
|
|
|
_isTimerRunning = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
//创建上传任务
|
|
|
|
|
|
public async Task ProcessUploadTasks()
|
|
|
|
|
|
{
|
|
|
|
|
|
_isUploading = true;
|
|
|
|
|
|
StartProgressTimer();
|
|
|
|
|
|
// 收集系统信息
|
|
|
|
|
|
//var systemInfo = SystemInfoCollector.Collect();
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// 存储到Redis
|
|
|
|
|
|
//await redis.StoreClientInfoAsync(systemInfo);
|
|
|
|
|
|
while (true)
|
|
|
|
|
|
{
|
|
|
|
|
|
//获取所有未完成的上传项
|
|
|
|
|
|
var pendingItems = 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 (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
//上传被取消
|
|
|
|
|
|
//await redis.DeleteClientAsync(systemInfo.MachineId);
|
|
|
|
|
|
}
|
|
|
|
|
|
finally
|
|
|
|
|
|
{
|
|
|
|
|
|
await Task.Delay(2000);
|
|
|
|
|
|
StopProgressTimer();
|
|
|
|
|
|
// 删除redis信息
|
|
|
|
|
|
//await redis.DeleteClientAsync(systemInfo.MachineId);
|
|
|
|
|
|
_isUploading = false;
|
|
|
|
|
|
UpLoadItems.Clear();
|
|
|
|
|
|
//加载上传完成列表
|
|
|
|
|
|
GetCompletedFiles();
|
|
|
|
|
|
if (MySetting.Instance.IsOn && !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();
|
|
|
|
|
|
// 获取滑块设置的速度限制(转换为字节 / 秒)
|
|
|
|
|
|
// 查询所有客户端
|
|
|
|
|
|
//var allClients = await redis.GetAllClientsAsync();
|
|
|
|
|
|
//var num = allClients == null ? 1 : allClients.Distinct().Count();
|
|
|
|
|
|
//var speedLimit = 10 * 1024 * 1024 / num/5;
|
|
|
|
|
|
|
|
|
|
|
|
var speedLimit = 100 * 1024 * 1024;
|
|
|
|
|
|
//var speedLimit = Convert.ToInt64(config["Minio:limitspeed"]);
|
|
|
|
|
|
var handler = new MinIOThrottledHandler(speedLimit,
|
|
|
|
|
|
new HttpClientHandler
|
|
|
|
|
|
{
|
|
|
|
|
|
// 保持 MinIO 必需的 SSL 配置
|
|
|
|
|
|
ServerCertificateCustomValidationCallback = (msg, cert, chain, errors) => true
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-07-04 16:39:35 +08:00
|
|
|
|
//var handler =
|
|
|
|
|
|
// new HttpClientHandler
|
|
|
|
|
|
// {
|
|
|
|
|
|
// // 保持 MinIO 必需的 SSL 配置
|
|
|
|
|
|
// ServerCertificateCustomValidationCallback = (msg, cert, chain, errors) => true
|
|
|
|
|
|
// };
|
|
|
|
|
|
|
2025-06-04 17:20:25 +08:00
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// 从配置获取MinIO设置更安全
|
|
|
|
|
|
IMinioClient client = new MinioClient()
|
|
|
|
|
|
.WithEndpoint(config["Minio:Endpoint"])
|
|
|
|
|
|
.WithCredentials(config["Minio:AccessKey"], config["Minio:SecretKey"])
|
2025-07-05 10:02:29 +08:00
|
|
|
|
.WithHttpClient(new HttpClient() { Timeout = TimeSpan.FromMinutes(30) })
|
2025-06-04 17:20:25 +08:00
|
|
|
|
.Build();
|
|
|
|
|
|
string bucketName = GetCurrentBucket();
|
|
|
|
|
|
// 确保桶存在
|
|
|
|
|
|
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 completionSource = new TaskCompletionSource<bool>();
|
|
|
|
|
|
var progress = new Progress<ProgressReport>(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.Value7 = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
|
string id = ut.Value4.ToString();
|
|
|
|
|
|
_uploadService.UpdateFileComplete(id);
|
|
|
|
|
|
CompleteItems.Add(ut);
|
|
|
|
|
|
ut.Value3 = "已完成";
|
|
|
|
|
|
UpdateUploadingItems();
|
|
|
|
|
|
_completeCount++;
|
|
|
|
|
|
FileCount = _completeCount + "/" + _uploadCount;
|
|
|
|
|
|
UpdateFileCounts();
|
|
|
|
|
|
// 刷新当前目录
|
|
|
|
|
|
_explorerBehavior?.RefreshMinIOPath(CurrentMinIOPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ut.Value3 = "上传中...";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (progressReport.Percentage == 100)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 延迟500ms确保MinIO完成处理
|
|
|
|
|
|
Task.Delay(500).ContinueWith(_ => { completionSource.TrySetResult(true); });
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 对对象名称进行URL编码
|
|
|
|
|
|
//string objectName = WebUtility.UrlEncode(ut.Value6);
|
|
|
|
|
|
var putObjectArgs = new PutObjectArgs()
|
|
|
|
|
|
.WithBucket(bucketName)
|
|
|
|
|
|
.WithObject(ut.Value6)
|
|
|
|
|
|
.WithFileName(ut.Value5)
|
|
|
|
|
|
.WithProgress(progress)
|
|
|
|
|
|
.WithObjectSize(5 * 1024 * 1024);
|
|
|
|
|
|
|
|
|
|
|
|
var uploadTask = client.PutObjectAsync(putObjectArgs);
|
|
|
|
|
|
await Task.WhenAny(uploadTask, completionSource.Task);
|
|
|
|
|
|
//await UploadVerifier.VerifyAsync(client, bucketName, objectName);
|
|
|
|
|
|
if (uploadTask.IsFaulted)
|
|
|
|
|
|
throw uploadTask.Exception;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
Application.Current.Dispatcher.Invoke(() => { ut.Value3 = $"上传失败: {ex.Message}"; });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//获取当前路径下的桶
|
|
|
|
|
|
private string GetCurrentBucket()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrEmpty(CurrentMinIOPath))
|
|
|
|
|
|
return string.Empty;
|
|
|
|
|
|
|
|
|
|
|
|
return CurrentMinIOPath.Split('/')[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//更新上传进行中及上传完成列表
|
|
|
|
|
|
private void UpdateFileCounts()
|
|
|
|
|
|
{
|
|
|
|
|
|
UploadingCount = UploadingItems.Count;
|
|
|
|
|
|
CompleteCount = CompleteItems.Count;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//关机
|
|
|
|
|
|
private void Shutdown()
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
Process.Start("shutdown", "/s /t 0");
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Win32Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
MessageBox.Show($"关机失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
2025-03-17 10:58:59 +08:00
|
|
|
|
}
|
2025-04-18 16:38:37 +08:00
|
|
|
|
}
|