// parameters: // downloader 要清除的 DynamicDownloader 对象。如果为 null,表示全部清除 void RemoveDownloader(DynamicDownloader downloader, bool bTriggerClose = false) { List <DynamicDownloader> list = new List <DynamicDownloader>(); lock (_syncRoot_downloaders) { if (downloader == null) { list.AddRange(_downloaders); _downloaders.Clear(); } else { list.Add(downloader); // downloader.Close(); _downloaders.Remove(downloader); } } foreach (DynamicDownloader current in list) { current.Close(); } }
void DisplayDownloaderErrorInfo(DynamicDownloader downloader) { if (string.IsNullOrEmpty(downloader.ErrorInfo) == false && downloader.ErrorInfo.StartsWith("~") == false) { this.Invoke((Action)(() => { MessageBox.Show(this, "下载 " + downloader.ServerFilePath + "-->" + downloader.LocalFilePath + " 过程中出错: " + downloader.ErrorInfo); })); downloader.ErrorInfo = "~" + downloader.ErrorInfo; // 只显示一次 } }
// result.Value: // -1 出错 // 0 不匹配 // 1 匹配 // exception: // 可能会抛出异常 public static NormalResult CheckMD5( this LibraryChannel channel, Stop stop, string strServerFilePath, string strLocalFilePath) { // 检查 MD5 // return: // -1 出错 // 0 文件没有找到 // 1 文件找到 int nRet = DynamicDownloader.GetServerFileMD5( channel, stop, // this.Stop, strServerFilePath, out byte[] server_md5, out string strError); if (nRet != 1) { strError = "探测服务器端文件 '" + strServerFilePath + "' MD5 时出错: " + strError; return(new NormalResult(-1, strError)); } using (FileStream stream = File.OpenRead(strLocalFilePath)) { stream.Seek(0, SeekOrigin.Begin); byte[] local_md5 = DynamicDownloader.GetFileMd5(stream); if (ByteArray.Compare(server_md5, local_md5) != 0) { strError = "服务器端文件 '" + strServerFilePath + "' 和本地文件 '" + strLocalFilePath + "' MD5 不匹配"; return(new NormalResult(0, strError)); } } return(new NormalResult(1, null)); }
// 下载动态文件 // 动态文件就是一直在不断增长的文件。允许一边增长一边下载 void menu_downloadDynamicFile(object sender, System.EventArgs e) { string strError = ""; if (this.DownloadFiles == null) { strError = "尚未绑定 DownloadFiles 事件"; goto ERROR1; } List <TreeNode> nodes = this.GetCheckedFileNodes(); if (nodes.Count == 0) { strError = "尚未选择要下载的配置文件节点"; goto ERROR1; } #if NO if (this.SelectedNode.ImageIndex != RESTYPE_FILE) { strError = "所选择的节点不是配置文件类型。请选择要下载的配置文件节点"; goto ERROR1; } #endif List <string> paths = new List <string>(); foreach (TreeNode node in nodes) { string strPath = GetNodePath(node); string strExt = Path.GetExtension(strPath); if (strExt == ".~state") { strError = "不允许下载扩展名为 .~state 的状态文件 (" + strPath + ")"; goto ERROR1; } paths.Add(strPath); } DownloadFilesEventArgs e1 = new DownloadFilesEventArgs(); e1.FileNames = paths; this.DownloadFiles(this, e1); if (string.IsNullOrEmpty(e1.ErrorInfo) == false) { goto ERROR1; } #if NO FolderBrowserDialog dir_dlg = new FolderBrowserDialog(); dir_dlg.Description = "请指定下载目标文件夹"; dir_dlg.RootFolder = Environment.SpecialFolder.MyComputer; dir_dlg.ShowNewFolderButton = true; dir_dlg.SelectedPath = _usedDownloadFolder; if (dir_dlg.ShowDialog() != DialogResult.OK) { return; } _usedDownloadFolder = dir_dlg.SelectedPath; string strTargetPath = Path.Combine(dir_dlg.SelectedPath, Path.GetFileName(strPath)); bool bAppend = false; // 是否继续下载? // 观察目标文件是否已经存在 if (File.Exists(strTargetPath)) { DialogResult result = MessageBox.Show(this, "目标文件 '" + strTargetPath + "' 已经存在。\r\n\r\n是否继续下载未完成部分?\r\n[是:从断点继续下载; 否: 重新从头下载; 取消:放弃下载]", "KernelResTree", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (result == DialogResult.Cancel) { return; } if (result == DialogResult.Yes) { bAppend = true; } } LibraryChannel channel = null; TimeSpan old_timeout = new TimeSpan(0); channel = this.CallGetChannel(true); old_timeout = channel.Timeout; channel.Timeout = new TimeSpan(0, 5, 0); FileDownloadDialog dlg = new FileDownloadDialog(); dlg.Font = this.Font; dlg.SourceFilePath = strPath; dlg.TargetFilePath = strTargetPath; // dlg.TopMost = true; dlg.Show(this); DynamicDownloader downloader = new DynamicDownloader(channel, strPath, strTargetPath); downloader.Tag = dlg; _downloaders.Add(downloader); downloader.Closed += new EventHandler(delegate(object o1, EventArgs e1) { if (channel != null) { channel.Timeout = old_timeout; this.CallReturnChannel(channel, true); channel = null; } DisplayDownloaderErrorInfo(downloader); RemoveDownloader(downloader); this.Invoke((Action)(() => { dlg.Close(); })); }); downloader.ProgressChanged += new DownloadProgressChangedEventHandler(delegate(object o1, DownloadProgressChangedEventArgs e1) { if (dlg.IsDisposed == false) { dlg.SetProgress(e1.BytesReceived, e1.TotalBytesToReceive); } }); dlg.FormClosed += new FormClosedEventHandler(delegate(object o1, FormClosedEventArgs e1) { downloader.Cancel(); if (channel != null) { channel.Timeout = old_timeout; this.CallReturnChannel(channel, true); channel = null; } DisplayDownloaderErrorInfo(downloader); RemoveDownloader(downloader); }); downloader.StartDownload(bAppend); #endif return; ERROR1: MessageBox.Show(this, strError); }
void GetMd5(DownloadFilesEventArgs e) { string strError = ""; List <string> lines = new List <string>(); CancellationTokenSource cancel = new CancellationTokenSource(); // 出现一个对话框,允许中断获取 MD5 的过程 FileDownloadDialog dlg = null; this.Invoke((Action)(() => { dlg = new FileDownloadDialog(); dlg.Font = this.Font; dlg.Text = $"正在获取 MD5"; // dlg.SourceFilePath = strTargetPath; dlg.TargetFilePath = null; // 让 Progress 变为走马灯状态 dlg.StartMarquee(); })); dlg.FormClosed += new FormClosedEventHandler(delegate(object o1, FormClosedEventArgs e1) { cancel.Cancel(); }); this.Invoke((Action)(() => { dlg.Show(this); })); var channel = Program.MainForm.GetChannel(this.ServerUrl); // var old_timeout = channel.Timeout; channel.Timeout = new TimeSpan(0, 25, 0); // this.ShowMessage("正在获取 MD5 ..."); try { foreach (string filepath in e.FileNames) { // this.ShowMessage($"正在获取服务器文件 {filepath} 的 MD5 ..."); dlg.SetProgress($"正在获取服务器文件 {filepath} 的 MD5 ...", 0, 0); // 检查 MD5 // return: // -1 出错 // 0 文件没有找到 // 1 文件找到 int nRet = DynamicDownloader.GetServerFileMD5ByTask( channel, null, // this.Stop, filepath, (MessagePromptEventHandler)null, cancel.Token, out byte[] server_md5, out strError); if (nRet != 1) { strError = "探测服务器端文件 '" + filepath + "' MD5 时出错: " + strError; goto ERROR1; } lines.Add($"文件 {filepath} 的 MD5 为 {Convert.ToBase64String(server_md5)}"); } } catch (Exception ex) { strError = ex.Message; goto ERROR1; } finally { //channel.Timeout = old_timeout; Program.MainForm.ReturnChannel(channel); // this.ClearMessage(); this.Invoke((Action)(() => { dlg.Close(); })); cancel.Dispose(); } this.Invoke((Action)(() => { MessageDialog.Show(this, StringUtil.MakePathList(lines, "\r\n")); })); return; ERROR1: ShowMessageBox(strError); }
// result.Value: // -1 出错 // 0 不匹配 // 1 匹配 // exception: // 可能会抛出异常 public static NormalResult CheckMD5( this LibraryChannel channel, Stop stop, string strServerFilePath, string strLocalFilePath, delegate_prompt prompt_func) { // stop 对中断 MD5 会起作用 Debug.Assert(stop != null, ""); // 2020/2/26 改为 ...ByTask() // 检查 MD5 // return: // -1 出错 // 0 文件没有找到 // 1 文件找到 int nRet = DynamicDownloader.GetServerFileMD5ByTask( channel, stop, // this.Stop, strServerFilePath, /* * new MessagePromptEventHandler(delegate (object o1, MessagePromptEventArgs e1) * { * //转换为 prompt_func 发生作用 * }), */ (o1, e1) => { if (prompt_func == null) { e1.ResultAction = "cancel"; return; } string[] buttons = e1.Actions.Split(new char[] { ',' }); //转换为 prompt_func 发生作用 e1.ResultAction = prompt_func(channel, e1.MessageText, buttons, 20); }, new System.Threading.CancellationToken(), out byte[] server_md5, out string strError);; if (nRet != 1) { strError = "探测服务器端文件 '" + strServerFilePath + "' MD5 时出错: " + strError; return(new NormalResult(-1, strError)); } using (FileStream stream = File.OpenRead(strLocalFilePath)) { stream.Seek(0, SeekOrigin.Begin); byte[] local_md5 = DynamicDownloader.GetFileMd5(stream); if (ByteArray.Compare(server_md5, local_md5) != 0) { strError = "服务器端文件 '" + strServerFilePath + "' 和本地文件 '" + strLocalFilePath + "' MD5 不匹配"; return(new NormalResult(0, strError)); } } return(new NormalResult(1, null)); }