// 装入一个日志文件中的若干记录 // parameters: // strStyle 如果包含 accessLog,表示这是需要获取只读日志 // strCacheDir 存储本地缓存文件的目录 // lServerFileSize 服务器端日志文件的尺寸。如果为-1,表示函数内会自动获取 // lSize 进度条所采用的最大尺寸。如果必要,可能会被本函数推动 // return: // -2 此类型的日志尚未启用 // -1 error // 0 正常结束 // 1 用户中断 static int ProcessFile( IWin32Window owner, Stop stop, ProgressEstimate estimate, LibraryChannel channel, string strLogFileName, int nLevel, long lServerFileSize, string strRange, string strStyle, string strCacheDir, object param, Delegate_doRecord procDoRecord, ref long lProgressValue, ref long lSize, out string strError) { strError = ""; int nRet = 0; long lRet = 0; stop.SetMessage("正在装入日志文件 " + strLogFileName + " 中的记录。" + "剩余时间 " + ProgressEstimate.Format(estimate.Estimate(lProgressValue)) + " 已经过时间 " + ProgressEstimate.Format(estimate.delta_passed)); bool bAccessLog = StringUtil.IsInList("accessLog", strStyle); string strXml = ""; long lAttachmentTotalLength = 0; byte[] attachment_data = null; long lFileSize = 0; if (lServerFileSize == -1) { lServerFileSize = 0; string strTempStyle = "level-" + nLevel.ToString(); if (bAccessLog) strTempStyle += ",accessLog"; // 获得服务器端日志文件尺寸 lRet = channel.GetOperLog( stop, strLogFileName, -1, // lIndex, -1, // lHint, strTempStyle, "", // strFilter out strXml, out lServerFileSize, 0, // lAttachmentFragmentStart, 0, // nAttachmentFramengLength, out attachment_data, out lAttachmentTotalLength, out strError); // 2015/11/25 if (lRet == -1) return -1; // 2010/12/13 if (lRet == 0) return 0; if (lServerFileSize == -1) { strError = "日志尚未启用"; return -2; } } Stream stream = null; bool bCacheFileExist = false; bool bRemoveCacheFile = false; // 是否要自动删除未全部完成的本地缓存文件 bool bAutoCache = StringUtil.IsInList("autocache", strStyle); if (bAutoCache == true) { nRet = PrepareCacheFile( strCacheDir, bAccessLog ? strLogFileName + ".a" : strLogFileName, lServerFileSize, out bCacheFileExist, out stream, out strError); if (nRet == -1) return -1; if (bCacheFileExist == false && stream != null) bRemoveCacheFile = true; } try { if (bCacheFileExist == true) lFileSize = stream.Length; else lFileSize = lServerFileSize; // stop.SetProgressRange(0, lTotalSize); if (String.IsNullOrEmpty(strRange) == true) strRange = "0-9999999999"; RangeList rl = new RangeList(strRange); for (int i = 0; i < rl.Count; i++) { RangeItem ri = (RangeItem)rl[i]; OperLogInfo[] records = null; long lStartRecords = 0; long lHint = -1; long lHintNext = -1; for (long lIndex = ri.lStart; lIndex < ri.lStart + ri.lLength; lIndex++) { Application.DoEvents(); if (stop != null) { if (stop.State != 0) { strError = "用户中断1"; goto ERROR1; } } if (lIndex == ri.lStart) lHint = -1; else lHint = lHintNext; if (bCacheFileExist == true) { if (lHint == -1) { // return: // -1 error // 0 成功 // 1 到达文件末尾或者超出 nRet = LocationRecord(stream, lIndex, out strError); if (nRet == -1) return -1; } else { // 根据暗示找到 if (lHint == stream.Length) break; if (lHint > stream.Length) { strError = "lHint参数值不正确"; return -1; } if (stream.Position != lHint) stream.Seek(lHint, SeekOrigin.Begin); } nRet = ReadCachedEnventLog( stream, out strXml, out lAttachmentTotalLength, out strError); if (nRet == -1) return -1; lHintNext = stream.Position; } else { if (records == null || lIndex - ri.lStart >= lStartRecords + records.Length) { int nCount = -1; if (ri.lLength >= Int32.MaxValue) nCount = -1; else nCount = (int)ri.lLength; string strTempStyle = "level-" + nLevel.ToString(); if (bAccessLog) strTempStyle += ",accessLog"; // 获得日志 // return: // -1 error // 0 file not found // 1 succeed // 2 超过范围,本次调用无效 lRet = channel.GetOperLogs( stop, strLogFileName, lIndex, lHint, nCount, strTempStyle, "", // strFilter out records, out strError); if (lRet == -1) { DialogResult result = MessageBox.Show(owner, strError + "\r\n\r\n是否继续处理?", "OperLogForm", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (result == DialogResult.No) goto ERROR1; else { // TODO: 是否要在listview中装入一条表示出错的行? lHintNext = -1; continue; } } if (lRet == 0) return 0; if (lRet == 2) break; // records数组表示的起点位置 lStartRecords = lIndex - ri.lStart; } OperLogInfo info = records[lIndex - lStartRecords]; strXml = info.Xml; lHintNext = info.HintNext; lAttachmentTotalLength = info.AttachmentLength; // 写入本地缓存的日志文件 if (stream != null) { try { WriteCachedEnventLog( stream, strXml, lAttachmentTotalLength); } catch (Exception ex) { strError = "写入本地缓存文件的时候出错: " + ex.Message; return -1; } } } #if NO // 2011/12/30 // 日志记录可能动态地增加了,超过了原先为ProgressBar设置的范围 if (lFizeTotalSize < (int)lHintNext) { lFizeTotalSize = lHintNext; stop.SetProgressRange(0, lFizeTotalSize); } #endif if (lHintNext >= 0) { // 校正 if (lProgressValue + lHintNext > lSize) { lSize = lProgressValue + lHintNext; stop.SetProgressRange(0, lSize); estimate.SetRange(0, lSize); } stop.SetProgressValue(lProgressValue + lHintNext); } if (lIndex % 100 == 0) { stop.SetMessage("正在装入日志文件 " + strLogFileName + " 中的记录 " + lIndex.ToString() + " 。" + "剩余时间 " + ProgressEstimate.Format(estimate.Estimate(lProgressValue + lHintNext)) + " 已经过时间 " + ProgressEstimate.Format(estimate.delta_passed)); } // if (procDoRecord != null) { nRet = procDoRecord(strLogFileName, strXml, bCacheFileExist, lHint, lIndex, lAttachmentTotalLength, param, out strError); if (nRet == -1) { DialogResult result = MessageBox.Show(owner, strLogFileName + " : " + lIndex.ToString() + "\r\n" + strError + "\r\n\r\n是否继续处理?", "OperLogForm", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (result == DialogResult.No) return -1; } if (nRet == 1) return 1; } } } // 创建本地缓存的日志文件的metadata文件 if (bCacheFileExist == false && stream != null) { nRet = CreateCacheMetadataFile( strCacheDir, bAccessLog ? strLogFileName + ".a" : strLogFileName, lServerFileSize, out strError); if (nRet == -1) goto ERROR1; } bRemoveCacheFile = false; // 不删除 } finally { if (stream != null) stream.Close(); if (bRemoveCacheFile == true) { string strError1 = ""; nRet = DeleteCacheFile( strCacheDir, bAccessLog ? strLogFileName + ".a" : strLogFileName, out strError1); if (nRet == -1) MessageBox.Show(owner, strError1); } } lProgressValue += lFileSize; return 0; ERROR1: return -1; }
// return: // -1 出错 // 0 正常结束 // 1 中断 /// <summary> /// 处理日志文件 /// </summary> /// <param name="owner">宿主窗口</param> /// <param name="stop">停止对象</param> /// <param name="estimate">剩余时间估算器</param> /// <param name="channel">通讯通道</param> /// <param name="filenames">要参与处理的日志文件名集合</param> /// <param name="nLevel">从 dp2Library 服务器获取日志记录的详细级别</param> /// <param name="strStyle">处理风格。autocache</param> /// <param name="strCacheDir">日志本地缓存目录</param> /// <param name="param">回调对象</param> /// <param name="procDoRecord">回调函数</param> /// <param name="strError">返回出错信息</param> /// <returns> /// -1 出错 /// 0 正常结束 /// 1 中断 /// </returns> public static int ProcessFiles( IWin32Window owner, Stop stop, ProgressEstimate estimate, LibraryChannel channel, List<string> filenames, int nLevel, string strStyle, string strCacheDir, object param, Delegate_doRecord procDoRecord, out string strError) { strError = ""; int nRet = 0; bool bAccessLog = StringUtil.IsInList("accessLog", strStyle); if (string.IsNullOrEmpty(strCacheDir) == false) PathUtil.CreateDirIfNeed(strCacheDir); // ProgressEstimate estimate = new ProgressEstimate(); bool bAutoCache = StringUtil.IsInList("autocache", strStyle); if (bAutoCache == true) { long lServerFileSize = 0; long lCacheFileSize = 0; // 象征性获得一个日志文件的尺寸,主要目的是为了触发一次通道登录 // return: // -1 error // 0 file not found // 1 found nRet = GetFileSize( stop, channel, strCacheDir, "20121001.log", bAccessLog, out lServerFileSize, out lCacheFileSize, out strError); if (nRet == -1) return -1; // 检查日志文件缓存目录的版本是否和当前用户的信息一致 // return: // -1 出错 // 0 一致 // 1 不一致 nRet = DetectCacheVersionFile( strCacheDir, "version.xml", channel.LibraryCodeList, channel.Url, out strError); if (nRet == -1) return -1; if (nRet == 1) { // 清空当前缓存目录 nRet = Global.DeleteDataDir( owner, strCacheDir, out strError); if (nRet == -1) return -1; PathUtil.CreateDirIfNeed(strCacheDir); // 重新创建目录 // 创建版本文件 nRet = CreateCacheVersionFile( strCacheDir, "version.xml", channel.LibraryCodeList, channel.Url, out strError); if (nRet == -1) return -1; } } long lTotalSize = 0; List<string> lines = new List<string>(); // 经过处理后排除了不存在的文件名 List<long> sizes = new List<long>(); stop.SetMessage("正在准备获得日志文件尺寸 ..."); foreach (string strLine in filenames) { Application.DoEvents(); if (stop != null && stop.State != 0) { strError = "用户中断"; return 1; } if (String.IsNullOrEmpty(strLine) == true) continue; string strFilename = strLine.Trim(); // 去掉注释 nRet = strFilename.IndexOf("#"); if (nRet != -1) strFilename = strFilename.Substring(0, nRet).Trim(); if (String.IsNullOrEmpty(strFilename) == true) continue; string strLogFilename = ""; string strRange = ""; nRet = strFilename.IndexOf(":"); if (nRet != -1) { strLogFilename = strFilename.Substring(0, nRet).Trim(); strRange = strFilename.Substring(nRet + 1).Trim(); } else { strLogFilename = strFilename.Trim(); strRange = ""; } long lServerFileSize = 0; long lCacheFileSize = 0; // 获得一个日志文件的尺寸 // return: // -1 error // 0 file not found // 1 found nRet = GetFileSize( stop, channel, strCacheDir, strLogFilename, bAccessLog, out lServerFileSize, out lCacheFileSize, out strError); if (nRet == -1) return -1; if (nRet == 0) continue; if (lServerFileSize == 0) continue; // 0字节的文件当作不存在处理 Debug.Assert(lServerFileSize >= 0, ""); if (bAutoCache == true) { if (lCacheFileSize > 0) lTotalSize += lCacheFileSize; else lTotalSize += lServerFileSize; } else { lTotalSize += lServerFileSize; } lines.Add(strFilename); // 记忆每个文件的尺寸,后面就不用获取了? sizes.Add(lServerFileSize); } if (stop != null) stop.SetProgressRange(0, lTotalSize); estimate.SetRange(0, lTotalSize); estimate.StartEstimate(); long lDoneSize = 0; for (int i = 0; i < lines.Count; i++) { Application.DoEvents(); if (stop != null && stop.State != 0) { strError = "用户中断"; return 1; } string strLine = lines[i]; #if NO if (String.IsNullOrEmpty(strLine) == true) continue; // 去掉注释 nRet = strLine.IndexOf("#"); if (nRet != -1) strLine = strLine.Substring(0, nRet).Trim(); if (String.IsNullOrEmpty(strLine) == true) continue; #endif string strLogFilename = ""; string strRange = ""; nRet = strLine.IndexOf(":"); if (nRet != -1) { strLogFilename = strLine.Substring(0, nRet).Trim(); strRange = strLine.Substring(nRet + 1).Trim(); } else { strLogFilename = strLine.Trim(); strRange = ""; } // return: // -1 error // 0 正常结束 // 1 用户中断 nRet = ProcessFile( owner, stop, estimate, channel, strLogFilename, nLevel, sizes[i], strRange, strStyle, strCacheDir, param, procDoRecord, ref lDoneSize, ref lTotalSize, out strError); if (nRet == -1) { if (stop != null) { if (stop.State != 0) return 0; } // MessageBox.Show(this, strError); DialogResult result = MessageBox.Show(owner, strError + "\r\n\r\n是否继续处理?", "OperLogForm", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1); if (result == DialogResult.No) return 1; } if (nRet == 1) return 1; } return 0; }
void RefreshLines(List<ListViewItem> items, bool bFillBiblioSummary) { string strError = ""; string strTimeMessage = ""; int nRet = 0; EnableControls(false); // MainForm.ShowProgress(true); stop.OnStop += new StopEventHandler(this.DoStop); stop.Initial("正在刷新 ..."); stop.BeginLoop(); try { stop.SetProgressRange(0, items.Count); ProgressEstimate estimate = new ProgressEstimate(); estimate.SetRange(0, items.Count); estimate.Start(); int nLineCount = 0; List<string> lines = new List<string>(); List<ListViewItem> part_items = new List<ListViewItem>(); for (int i = 0; i < items.Count; i++) { if (stop.State != 0) { strError = "用户中断1"; goto ERROR1; } ListViewItem item = items[i]; stop.SetMessage("正在刷新 " + item.Text + " ..."); stop.SetProgressValue(i); string strRecPath = ListViewUtil.GetItemText(item, COLUMN_RECPATH); lines.Add(strRecPath); part_items.Add(item); if (lines.Count >= 100) { if (lines.Count > 0) stop.SetMessage("(" + i.ToString() + " / " + nLineCount.ToString() + ") 正在装入路径 " + lines[0] + " 等记录。" + "剩余时间 " + ProgressEstimate.Format(estimate.Estimate(i)) + " 已经过时间 " + ProgressEstimate.Format(estimate.delta_passed)); // 处理一小批记录的装入 nRet = DoLoadRecords(lines, part_items, bFillBiblioSummary, new string [] {"summary","@isbnissn"}, out strError); if (nRet == -1) goto ERROR1; lines.Clear(); part_items.Clear(); } } // 最后剩下的一批 if (lines.Count > 0) { if (lines.Count > 0) stop.SetMessage("(" + nLineCount.ToString() + " / " + nLineCount.ToString() + ") 正在装入路径 " + lines[0] + " 等记录..."); // 处理一小批记录的装入 nRet = DoLoadRecords(lines, part_items, bFillBiblioSummary, new string[] { "summary", "@isbnissn" }, out strError); if (nRet == -1) goto ERROR1; lines.Clear(); part_items.Clear(); } strTimeMessage = "共刷新册信息 " + nLineCount.ToString() + " 条。耗费时间: " + estimate.GetTotalTime().ToString(); } finally { stop.EndLoop(); stop.OnStop -= new StopEventHandler(this.DoStop); stop.Initial("刷新完成。"); stop.HideProgress(); EnableControls(true); // MainForm.ShowProgress(false); } return; ERROR1: MessageBox.Show(this, strError); }
// 从记录路径文件装载 /// <summary> /// 从记录路径文件装载 /// </summary> /// <param name="strRecPathFilename">记录路径文件名(全路径)</param> /// <param name="bClearBefore">是否要在装载前情况浏览列表</param> /// <param name="strError">返回出错信息</param> /// <returns>-1: 出错,错误信息在 strError 参数返回; 0: 成功</returns> public int LoadFromRecPathFile(string strRecPathFilename, bool bClearBefore, out string strError) { strError = ""; int nRet = 0; if (bClearBefore == true) ClearBefore(); string strTimeMessage = ""; StreamReader sr = null; try { // 打开文件 sr = new StreamReader(strRecPathFilename); EnableControls(false); // MainForm.ShowProgress(true); stop.OnStop += new StopEventHandler(this.DoStop); stop.Initial("正在初始化浏览器组件 ..."); stop.BeginLoop(); this.Update(); this.MainForm.Update(); try { // this.m_nGreenItemCount = 0; // 逐行读入文件内容 // 测算文件行数 int nLineCount = 0; for (; ; ) { if (stop != null) { if (stop.State != 0) { strError = "用户中断1"; goto ERROR1; } } string strLine = ""; strLine = sr.ReadLine(); if (strLine == null) break; strLine = strLine.Trim(); if (String.IsNullOrEmpty(strLine) == true) continue; // 检查路径所从属书目库是否为图书/期刊库? // return: // -1 error // 0 不符合要求。提示信息在strError中 // 1 符合要求 nRet = CheckItemRecPath(this.comboBox_load_type.Text, strLine, out strError); if (nRet == -1) goto ERROR1; if (nRet == 0) { GetErrorInfoForm().WriteHtml(strError + "\r\n"); } nLineCount++; // stop.SetMessage("正在装入册条码号 " + strLine + " 对应的记录..."); } // 设置进度范围 stop.SetProgressRange(0, nLineCount); sr.Close(); ProgressEstimate estimate = new ProgressEstimate(); estimate.SetRange(0, nLineCount); estimate.Start(); List<string> lines = new List<string>(); // 正式开始处理 sr = new StreamReader(strRecPathFilename); for (int i = 0; ; i++) { if (stop != null) { if (stop.State != 0) { strError = "用户中断1"; goto ERROR1; } } string strLine = ""; strLine = sr.ReadLine(); stop.SetProgressValue(i); if (strLine == null) break; strLine = strLine.Trim(); if (String.IsNullOrEmpty(strLine) == true) continue; if (strLine[0] == '#') continue; // 注释行 lines.Add(strLine); if (lines.Count >= 100) { if (lines.Count > 0) stop.SetMessage("(" + i.ToString() + " / " + nLineCount.ToString() + ") 正在装入路径 " + lines[0] + " 等记录。" + "剩余时间 " + ProgressEstimate.Format(estimate.Estimate(i)) + " 已经过时间 " + ProgressEstimate.Format(estimate.delta_passed)); // 处理一小批记录的装入 nRet = DoLoadRecords(lines, null, out strError); if (nRet == -1) goto ERROR1; lines.Clear(); } } // 最后剩下的一批 if (lines.Count > 0) { if (lines.Count > 0) stop.SetMessage("(" + nLineCount.ToString() + " / " + nLineCount.ToString() + ") 正在装入路径 " + lines[0] + " 等记录..."); // 处理一小批记录的装入 nRet = DoLoadRecords(lines, null, out strError); if (nRet == -1) goto ERROR1; lines.Clear(); } strTimeMessage = "共装入册记录 " + nLineCount.ToString() + " 条。耗费时间: " + estimate.GetTotalTime().ToString(); } finally { stop.EndLoop(); stop.OnStop -= new StopEventHandler(this.DoStop); stop.Initial("装入完成。"); stop.HideProgress(); EnableControls(true); // MainForm.ShowProgress(false); } } catch (Exception ex) { strError = ex.Message; goto ERROR1; } finally { sr.Close(); } this.MainForm.StatusBarMessage = strTimeMessage; return 0; ERROR1: return -1; }
/// <summary> /// 刷新若干浏览行 /// </summary> /// <param name="nRecPathColumn">记录路径列的列号</param> /// <param name="items">要刷新的行事项数组</param> /// <param name="bFillBiblioSummary">是否要填充书目摘要列</param> /// <param name="summary_col_names">书目摘要列名数组</param> public virtual void RefreshLines( int nRecPathColumn, List<ListViewItem> items, bool bFillBiblioSummary, string[] summary_col_names) { string strError = ""; string strTimeMessage = ""; int nRet = 0; if (this.InvokeRequired == false) EnableControls(false); // MainForm.ShowProgress(true); stop.OnStop += new StopEventHandler(this.DoStop); if (this.InvokeRequired == false) stop.Initial("正在刷新 ..."); stop.BeginLoop(); try { if (this.InvokeRequired == false) stop.SetProgressRange(0, items.Count); ProgressEstimate estimate = new ProgressEstimate(); estimate.SetRange(0, items.Count); estimate.StartEstimate(); int nLineCount = 0; List<string> lines = new List<string>(); List<ListViewItem> part_items = new List<ListViewItem>(); for (int i = 0; i < items.Count; i++) { Application.DoEvents(); if (stop.State != 0) { strError = "用户中断1"; goto ERROR1; } ListViewItem item = items[i]; if (this.InvokeRequired == false) { stop.SetMessage("正在刷新 " + item.Text + " ..."); stop.SetProgressValue(i); } string strRecPath = ListViewUtil.GetItemText(item, nRecPathColumn); if (string.IsNullOrEmpty(strRecPath) == true) continue; lines.Add(strRecPath); part_items.Add(item); if (lines.Count >= 100) { if (this.InvokeRequired == false) { if (lines.Count > 0) stop.SetMessage("(" + i.ToString() + " / " + nLineCount.ToString() + ") 正在装入路径 " + lines[0] + " 等记录。" + "剩余时间 " + ProgressEstimate.Format(estimate.Estimate(i)) + " 已经过时间 " + ProgressEstimate.Format(estimate.delta_passed)); } // 处理一小批记录的装入 nRet = DoLoadRecords(lines, part_items, bFillBiblioSummary, summary_col_names, out strError); if (nRet == -1) goto ERROR1; lines.Clear(); part_items.Clear(); } } // 最后剩下的一批 if (lines.Count > 0) { if (this.InvokeRequired == false) { if (lines.Count > 0) stop.SetMessage("(" + nLineCount.ToString() + " / " + nLineCount.ToString() + ") 正在装入路径 " + lines[0] + " 等记录..."); } // 处理一小批记录的装入 nRet = DoLoadRecords(lines, part_items, bFillBiblioSummary, summary_col_names, out strError); if (nRet == -1) goto ERROR1; lines.Clear(); part_items.Clear(); } strTimeMessage = "共刷新册信息 " + nLineCount.ToString() + " 条。耗费时间: " + estimate.GetTotalTime().ToString(); } finally { stop.EndLoop(); stop.OnStop -= new StopEventHandler(this.DoStop); if (this.InvokeRequired == false) { stop.Initial("刷新完成。"); stop.HideProgress(); } if (this.InvokeRequired == false) EnableControls(true); // MainForm.ShowProgress(false); } return; ERROR1: if (this.InvokeRequired == false) MessageBox.Show(this, strError); else stop.SetMessage(strError); }
// 上传文件到到 dp2lbrary 服务器 // parameters: // timestamp 时间戳。如果为 null,函数会自动根据文件信息得到一个时间戳 // bRetryOverwiteExisting 是否自动在时间戳不一致的情况下覆盖已经存在的服务器文件。== true,表示当发现时间戳不一致的时候,自动用返回的时间戳重试覆盖 // return: // -1 出错 // 0 上传文件成功 int UploadFile( Stop stop, LibraryChannel channel, string strClientFilePath, string strServerFilePath, string strStyle, byte[] timestamp, bool bRetryOverwiteExisting, out string strError) { strError = ""; string strResPath = strServerFilePath; #if NO string strMime = API.MimeTypeFrom(ResObjectDlg.ReadFirst256Bytes(strClientFilePath), ""); #endif string strMime = PathUtil.MimeTypeFrom(strClientFilePath); // 检测文件尺寸 FileInfo fi = new FileInfo(strClientFilePath); if (fi.Exists == false) { strError = "文件 '" + strClientFilePath + "' 不存在..."; return -1; } string[] ranges = null; if (fi.Length == 0) { // 空文件 ranges = new string[1]; ranges[0] = ""; } else { string strRange = ""; strRange = "0-" + (fi.Length - 1).ToString(); // 按照100K作为一个chunk // TODO: 实现滑动窗口,根据速率来决定chunk尺寸 ranges = RangeList.ChunkRange(strRange, channel.UploadResChunkSize // 500 * 1024 ); } if (timestamp == null) timestamp = FileUtil.GetFileTimestamp(strClientFilePath); byte[] output_timestamp = null; // REDOWHOLESAVE: string strWarning = ""; bool bCharRedo = false; // 是否正在击键重做的过程中 TimeSpan old_timeout = channel.Timeout; channel.Timeout = TimeSpan.FromSeconds(10); int nCursorLeft = Console.CursorLeft; int nCursorTop = Console.CursorTop; ProgressEstimate _estimate = new ProgressEstimate(); _estimate.SetRange(0, fi.Length); _estimate.StartEstimate(); string strTotalSize = GetSizeString(fi.Length); try { for (int j = 0; j < ranges.Length; j++) { if (stop != null && stop.State != 0) { strError = "用户中断"; goto ERROR1; } RangeList rl = new RangeList(ranges[j]); long uploaded = ((RangeItem)rl[0]).lStart; string strPercent = ""; if (rl.Count >= 1) { double ratio = (double)uploaded / (double)fi.Length; strPercent = String.Format("{0,3:N}", ratio * (double)100) + "%"; } string strUploadedSize = GetSizeString(uploaded); string strWaiting = ""; if (j == ranges.Length - 1) { strWaiting = " please wait ..."; channel.Timeout = new TimeSpan(0, 40, 0); // 40 分钟 } else if (j > 0) strWaiting = "剩余时间 " + ProgressEstimate.Format(_estimate.Estimate(uploaded)) + " 已经过时间 " + ProgressEstimate.Format(_estimate.delta_passed); #if NO if (stop != null) stop.SetMessage( // strMessagePrefix + "正在上载 " + ranges[j] + "/" + Convert.ToString(fi.Length) + " " + strPercent + " " + strClientFilePath + strWarning + strWaiting); #endif ProgressMessage(nCursorLeft, nCursorTop, "uploading " // + ranges[j] + "/" + Convert.ToString(fi.Length) + " " + strPercent + " " + strUploadedSize + "/" + strTotalSize + " " // + strClientFilePath + strWarning + strWaiting); int nRedoCount = 0; REDO: long lRet = channel.SaveResObject( stop, strResPath, strClientFilePath, strClientFilePath, strMime, ranges[j], // j == ranges.Length - 1 ? true : false, // 最尾一次操作,提醒底层注意设置特殊的WebService API超时时间 timestamp, strStyle, out output_timestamp, out strError); timestamp = output_timestamp; strWarning = ""; if (lRet == -1) { // 如果是第一个 chunk,自动用返回的时间戳重试一次覆盖 if (bRetryOverwiteExisting == true && j == 0 && channel.ErrorCode == DigitalPlatform.LibraryClient.localhost.ErrorCode.TimestampMismatch && nRedoCount == 0) { nRedoCount++; goto REDO; } if (channel.ErrorCode == DigitalPlatform.LibraryClient.localhost.ErrorCode.TimestampMismatch && bCharRedo == true) { bCharRedo = false; goto REDO; } Console.WriteLine("出错: " + strError + "\r\n\r\n是否重试? (Y/N)"); ConsoleKeyInfo info = Console.ReadKey(); if (info.KeyChar == 'y' || info.KeyChar == 'Y') { Console.WriteLine(); nCursorLeft = Console.CursorLeft; nCursorTop = Console.CursorTop + 2; bCharRedo = true; goto REDO; } goto ERROR1; } bCharRedo = false; } } finally { channel.Timeout = old_timeout; ProgressMessage(nCursorLeft, nCursorTop, ""); } return 0; ERROR1: return -1; }