// 上载一个res // parameter: // inputfile: 源流 // bIsFirstRes: 是否是第一个资源(xml) // strError: error info // return: // -2 片断中发现时间戳不匹配。本函数调主可重上载整个资源 // -1 error // 0 successed public int DoResUpload( ref RmsChannel channel, ref string strRecordPath, Stream inputfile, ref DbNameMap map, bool bIsFirstRes, string strCount, out string strError) { strError = ""; int nRet; long lBodyStart = 0; long lBodyLength = 0; // 1. 从输入流中得到strMetadata,与body(body放到一个临时文件里) string strMetaDataXml = ""; nRet = GetResInfo(inputfile, bIsFirstRes, out strMetaDataXml, out lBodyStart, out lBodyLength, out strError); if (nRet == -1) goto ERROR1; if (lBodyLength == 0) return 0; // 空包不需上载 // 2.为上载做准备 XmlDocument metadataDom = new XmlDocument(); try { metadataDom.LoadXml(strMetaDataXml); } catch (Exception ex) { strError = "加载元数据到dom出错!\r\n" + ex.Message; goto ERROR1; } XmlNode node = metadataDom.DocumentElement; string strResPath = DomUtil.GetAttr(node, "path"); string strTargetPath = ""; if (bIsFirstRes == true) // 第一个资源 { // 从map中查询覆盖还是追加? ResPath respath = new ResPath(strResPath); respath.MakeDbName(); REDO: DbNameMapItem mapItem = (DbNameMapItem)map["*"]; if (mapItem != null) { } else { mapItem = (DbNameMapItem)map[respath.FullPath.ToUpper()]; } if (mapItem == null) { OriginNotFoundDlg dlg = new OriginNotFoundDlg(); MainForm.SetControlFont(dlg, this.DefaultFont); dlg.Message = "数据中声明的数据库路径 '" + respath.FullPath + "' 在覆盖关系对照表中没有找到, 请选择覆盖方式: "; dlg.Origin = respath.FullPath.ToUpper(); dlg.Servers = this.Servers; dlg.Channels = this.Channels; dlg.Map = map; dlg.StartPosition = FormStartPosition.CenterScreen; dlg.ShowDialog(this); if (dlg.DialogResult != DialogResult.OK) { strError = "用户中断..."; goto ERROR1; } map = dlg.Map; goto REDO; } if (mapItem.Style == "skip") return 0; // 构造目标路径 // 1)从源路径中提取id。源路径来自备份文件数据 respath = new ResPath(strResPath); string strID = respath.GetRecordId(); if (strID == null || strID == "" || (mapItem.Style == "append") ) { strID = "?"; // 将来加一个对话框 } // 2)用目标库路径构造完整的记录路径 string strTargetFullPath = ""; if (mapItem.Target == "*") { respath = new ResPath(strResPath); respath.MakeDbName(); strTargetFullPath = respath.FullPath; } else { strTargetFullPath = mapItem.Target; } respath = new ResPath(strTargetFullPath); strTargetPath = respath.Path + "/" + strID; strRecordPath = strTargetPath; channel = this.Channels.GetChannel(respath.Url); } else // 第二个以后的资源 { if (channel == null) { strError = "当bIsFirstRes==false时,参数channel不应为null..."; goto ERROR1; } ResPath respath = new ResPath(strResPath); string strObjectId = respath.GetObjectId(); if (strObjectId == null || strObjectId == "") { strError = "object id为空..."; goto ERROR1; } strTargetPath = strRecordPath + "/object/" + strObjectId; if (strRecordPath == "") { strError = "strRecordPath参数值为空..."; goto ERROR1; } } // string strLocalPath = DomUtil.GetAttr(node,"localpath"); // string strMimeType = DomUtil.GetAttr(node,"mimetype"); string strTimeStamp = DomUtil.GetAttr(node, "timestamp"); // 注意,strLocalPath并不是要上载的body文件,它只用来作元数据\ // body文件为strBodyTempFileName // 3.将body文件拆分成片断进行上载 string[] ranges = null; if (lBodyLength == 0) { // 空文件 ranges = new string[1]; ranges[0] = ""; } else { string strRange = ""; strRange = "0-" + Convert.ToString(lBodyLength - 1); // 按照100K作为一个chunk ranges = RangeList.ChunkRange(strRange, 100 * 1024 ); } byte[] timestamp = ByteArray.GetTimeStampByteArray(strTimeStamp); byte[] output_timestamp = null; REDOWHOLESAVE: string strOutputPath = ""; string strWarning = ""; for (int j = 0; j < ranges.Length; j++) { REDOSINGLESAVE: Application.DoEvents(); // 出让界面控制权 if (stop.State != 0) { DialogResult result = MessageBox.Show(this, "确实要中断当前批处理操作?", "dp2batch", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2); if (result == DialogResult.Yes) { strError = "用户中断"; goto ERROR1; } else { stop.Continue(); } } string strWaiting = ""; if (j == ranges.Length - 1) strWaiting = " 请耐心等待..."; string strPercent = ""; RangeList rl = new RangeList(ranges[j]); if (rl.Count >= 1) { double ratio = (double)((RangeItem)rl[0]).lStart / (double)lBodyLength; strPercent = String.Format("{0,3:N}", ratio * (double)100) + "%"; } if (stop != null) stop.SetMessage("正在上载 " + ranges[j] + "/" + Convert.ToString(lBodyLength) + " " + strPercent + " " + strTargetPath + strWarning + strWaiting + " " + strCount); inputfile.Seek(lBodyStart, SeekOrigin.Begin); long lRet = channel.DoSaveResObject(strTargetPath, inputfile, lBodyLength, "", // style strMetaDataXml, ranges[j], j == ranges.Length - 1 ? true : false, // 最尾一次操作,提醒底层注意设置特殊的WebService API超时时间 timestamp, out output_timestamp, out strOutputPath, out strError); // progressBar_main.Value = (int)((inputfile.Position)/ProgressRatio); stop.SetProgressValue(inputfile.Position); strWarning = ""; if (lRet == -1) { if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch) { string strDisplayRecPath = strOutputPath; if (string.IsNullOrEmpty(strDisplayRecPath) == true) strDisplayRecPath = strTargetPath; if (this.bNotAskTimestampMismatchWhenOverwrite == true) { timestamp = new byte[output_timestamp.Length]; Array.Copy(output_timestamp, 0, timestamp, 0, output_timestamp.Length); strWarning = " (时间戳不匹配, 自动重试)"; if (ranges.Length == 1 || j == 0) goto REDOSINGLESAVE; goto REDOWHOLESAVE; } DialogResult result = MessageDlg.Show(this, "上载 '" + strDisplayRecPath + "' (片断:" + ranges[j] + "/总尺寸:" + Convert.ToString(lBodyLength) + ") 时发现时间戳不匹配。详细情况如下:\r\n---\r\n" + strError + "\r\n---\r\n\r\n是否以新时间戳强行上载?\r\n注:(是)强行上载 (否)忽略当前记录或资源上载,但继续后面的处理 (取消)中断整个批处理", "dp2batch", MessageBoxButtons.YesNoCancel, MessageBoxDefaultButton.Button1, ref this.bNotAskTimestampMismatchWhenOverwrite); if (result == DialogResult.Yes) { if (output_timestamp != null) { timestamp = new byte[output_timestamp.Length]; Array.Copy(output_timestamp, 0, timestamp, 0, output_timestamp.Length); } else { timestamp = output_timestamp; } strWarning = " (时间戳不匹配, 应用户要求重试)"; if (ranges.Length == 1 || j == 0) goto REDOSINGLESAVE; goto REDOWHOLESAVE; } if (result == DialogResult.No) { return 0; // 继续作后面的资源 } if (result == DialogResult.Cancel) { strError = "用户中断"; goto ERROR1; // 中断整个处理 } } goto ERROR1; } timestamp = output_timestamp; } // 考虑到保存第一个资源的时候,id可能为“?”,因此需要得到实际的id值 if (bIsFirstRes) strRecordPath = strOutputPath; return 0; ERROR1: return -1; }
// return: // -1 出错 // 0 成功 public int UploadObjects( Stop stop, RmsChannel channel, List<UploadRecord> records, ref bool bDontPromptTimestampMismatchWhenOverwrite, out string strError) { strError = ""; int nRet = 0; foreach (UploadRecord record in records) { if (record.ResList == null || record.ResList.Count <= 1) continue; int i = 0; foreach (OneRes res in record.ResList) { if (i == 0) { i++; continue; } // record.RecordBody.Path; // 注意检查里面不能有问号 ResPath temp = new ResPath(res.Path); // 检查 object id string strID = temp.GetObjectId(); string strObjectPath = record.RecordBody.Path + "/object/" + strID; int nRedoCount = 0; REDO: // 上载一个res // parameters: // strRecordPath 主记录的路径 // inputfile: 源流 // bIsFirstRes: 是否是第一个资源(xml) // strError: error info // return: // -2 片断中发现时间戳不匹配。本函数调主可重上载整个资源 // -1 error // 0 successed nRet = UploadOneRes( this.m_owner, stop, channel, ref strObjectPath, this.Stream, res, false, "", // strCount, ref bDontPromptTimestampMismatchWhenOverwrite, out strError); if (nRet == -1) { // 如果 channel.ErrorCode == ChannelErrorCode.NotFound // 表示元数据记录不存在,或者其中对应 id 的 <dprms:file> 元素不存在 return -1; } if (nRet == -2) { // TODO: 防止死循环 nRedoCount++; if (nRedoCount > 3) { return -1; } goto REDO; } i++; } } return 0; }