// 从 .dp2bak 文件中读出每个资源的主要信息 // 本函数调用前,文件指针在整个记录的开始位置 // return: // -1 出错 // 0 正常 // 1 结束。此次API不返回有效的XML记录 int ReadResFrameInfo( out List<OneRes> reslist, out string strError) { strError = ""; reslist = new List<OneRes>(); long lStart = this.Stream.Position; byte[] data = new byte[8]; int nRet = this.Stream.Read(data, 0, 8); if (nRet == 0) return 1; // 已经结束 if (nRet < 8) { strError = "read whole length error..."; return -1; } // 毛长度 long lLength = BitConverter.ToInt64(data, 0); #if NO if (bSkip == true) { file.Seek(lLength, SeekOrigin.Current); return 0; } #endif for (int i = 0; ; i++) { if (this.Stream.Position - lStart >= lLength + 8) break; long lBodyStart = 0; long lBodyLength = 0; // 1. 从输入流中得到strMetadata,与body(body放到一个临时文件里) string strMetaDataXml = ""; nRet = GetResInfo(this.Stream, i == 0 ? true : false, out strMetaDataXml, out lBodyStart, out lBodyLength, out strError); if (nRet == -1) return -1; if (lBodyLength == 0) continue; // 空包不需上载 OneRes res = new OneRes(); res.MetadataXml = strMetaDataXml; res.StartOffs = lBodyStart; res.Length = lBodyLength; reslist.Add(res); // 取出原始记录路径 XmlDocument metadataDom = new XmlDocument(); try { metadataDom.LoadXml(strMetaDataXml); } catch (Exception ex) { strError = "加载 metadataxml 到 DOM 时出错:" + ex.Message; return -1; } res.Path = DomUtil.GetAttr(metadataDom.DocumentElement, "path"); string strTimeStamp = DomUtil.GetAttr(metadataDom.DocumentElement, "timestamp"); res.Timestamp = ByteArray.GetTimeStampByteArray(strTimeStamp); } return 0; }
// 上载一个res // parameters: // strRecordPath 主记录的路径 // inputfile: 源流 // bIsFirstRes: 是否是第一个资源(xml) // strError: error info // return: // -2 片断中发现时间戳不匹配。本函数调主可重上载整个资源 // -1 error // 0 successed public static int UploadOneRes( IWin32Window owner, Stop stop, RmsChannel channel, ref string strRecordPath, Stream inputfile, OneRes res, // ref DbNameMap map, bool bIsFirstRes, string strCount, ref bool bDontPromptTimestampMismatchWhenOverwrite, out string strError) { strError = ""; int nRet = 0; if (res.Length == 0) { Debug.Assert(false, ""); return 0; // 空包不需上载 } #if NO // 2.为上载做准备 XmlDocument metadataDom = new XmlDocument(); try { metadataDom.LoadXml(res.MetadataXml); } catch (Exception ex) { strError = "加载 metadataxml 到 DOM 时出错: " + ex.Message; goto ERROR1; } XmlNode node = metadataDom.DocumentElement; string strResPath = DomUtil.GetAttr(node, "path"); string strTargetPath = ""; // string strLocalPath = DomUtil.GetAttr(node,"localpath"); // string strMimeType = DomUtil.GetAttr(node,"mimetype"); string strTimeStamp = DomUtil.GetAttr(node, "timestamp"); // 注意,strLocalPath并不是要上载的body文件,它只用来作元数据\ // body文件为strBodyTempFileName #endif // string strTargetPath = strRecordPath; // 3.将body文件拆分成片断进行上载 string[] ranges = null; if (res.Length == 0) { // 空文件 ranges = new string[1]; ranges[0] = ""; } else { string strRange = ""; strRange = "0-" + Convert.ToString(res.Length - 1); // 按照100K作为一个chunk ranges = RangeList.ChunkRange(strRange, 100 * 1024 ); } byte[] timestamp = res.Timestamp; 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(owner, "确实要中断当前批处理操作?", "导入数据", 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)res.Length; strPercent = String.Format("{0,3:N}", ratio * (double)100) + "%"; } if (stop != null) stop.SetMessage("正在保存 " + ranges[j] + "/" + Convert.ToString(res.Length) + " " + strPercent + " " + strRecordPath + strWarning + strWaiting + " " + strCount); inputfile.Seek(res.StartOffs, SeekOrigin.Begin); long lRet = channel.DoSaveResObject(strRecordPath, inputfile, res.Length, "", // style res.MetadataXml, ranges[j], j == ranges.Length - 1 ? true : false, // 最尾一次操作,提醒底层注意设置特殊的WebService API超时时间 timestamp, out output_timestamp, out strOutputPath, out strError); // stop.SetProgressValue(inputfile.Position); strWarning = ""; if (lRet == -1) { if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch) { string strDisplayRecPath = strOutputPath; if (string.IsNullOrEmpty(strDisplayRecPath) == true) strDisplayRecPath = strRecordPath; if (bDontPromptTimestampMismatchWhenOverwrite == 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(owner, "保存 '" + strDisplayRecPath + "' (片断:" + ranges[j] + "/总尺寸:" + Convert.ToString(res.Length) + ") 时发现时间戳不匹配。详细情况如下:\r\n---\r\n" + strError + "\r\n---\r\n\r\n是否以新时间戳强行覆盖保存?\r\n注:\r\n[是] 强行覆盖保存\r\n[否] 忽略当前记录或资源保存,但继续后面的处理\r\n[取消] 中断整个批处理", "导入数据", MessageBoxButtons.YesNoCancel, MessageBoxDefaultButton.Button1, ref bDontPromptTimestampMismatchWhenOverwrite); 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; }