public static string[] UriToCassetteAndPath(this string uri) { var substrs = uri.Split(new[] { "@iis.nsk.su" }, StringSplitOptions.None); if (substrs.Length != 2) { LOG.WriteLine("strange uri " + uri); } return(substrs);// Tuple.Create(substrs[0], substrs[1]); }
public static bool ExtractArchiveToMemory(string cassetteName, string inArchivePath, string archivePath, string archiveName) { archivePath += archiveName + ".sarc"; if (!File.Exists(archivePath)) { LOG.WriteLine("не найден файл " + archivePath); return(false); } if (reCache || CacheInArchives.Count > 100000) { // lock (CacheTables) CacheInArchives.Clear(); // lock (CachedArchives) CachedArchives.Clear(); } using (Stream read = File.Open(archivePath, FileMode.Open)) try { var tableLengthBytes = new byte[MaxTableLengthLength]; read.Read(tableLengthBytes, 0, tableLengthBytes.Length); var tableLengthString = TableLengthEncoding.GetString(tableLengthBytes); int tableLength; if (!int.TryParse(tableLengthString, out tableLength)) { LOG.WriteLine(tableLength + " is Not Long in " + archivePath); return(false); } var tableBytes = new byte[tableLength]; read.Read(tableBytes, 0, tableLength); var xTable = XElement.Parse(TableEncoding.GetString(tableBytes)); foreach (var i in xTable.Elements().ToDictionary( //AsParallel() x => cassetteName + "/" + archiveName + "/" + x.Element("path").Value, x => { long newVal1 = -1, newVal2 = -1; if (x.Element("start") == null || !long.TryParse(x.Element("start").Value, out newVal1) || x.Element("length") == null || !long.TryParse(x.Element("length").Value, out newVal2)) { LOG.WriteLine("can't parse " + x.ToString() + " to long in " + archivePath); } return(new KeyValuePair <long, long>(newVal1, newVal2)); })) { CacheInArchives.Add(i.Key, i.Value); } return(true); } catch { return(false); } }
public static void Create(this string path, Dictionary <string, string> filesAndDirsRelativePaths) { //var fileTable=new StreamWriter(path+".txt"); var filesRelativePaths = AddFolderSubfiles(filesAndDirsRelativePaths.ToDictionary(i => i.Key, i => i.Value)); using (var fileAllOrigin = new MemoryStream()) using (var fileAll = File.Create(path)) { var startFileTable = new Dictionary <string, long>(); var endFileTable = new Dictionary <string, long>(); foreach (var file in filesRelativePaths) { using (var fileStream = File.OpenRead(file.Key)) { startFileTable.Add(file.Value, fileAllOrigin.Length); endFileTable.Add(file.Value, fileStream.Length); var bytes = new byte[fileStream.Length]; fileStream.Read(bytes, 0, bytes.Length); fileAllOrigin.Write(bytes, 0, bytes.Length); } } var xTable = new XElement("table", new XAttribute("version", "25.05.2012"), endFileTable.Select(i => new XElement("file", new XElement("path", i.Key), new XElement("start", startFileTable[i.Key]), new XElement("length", i.Value)))); var tableBytes = TableEncoding.GetBytes(xTable.ToString()); var tableLengthbytes = TableLengthEncoding.GetBytes(tableBytes.Length.ToString()); //int MaxTableLengthLength = 13; if (tableLengthbytes.Length > MaxTableLengthLength) { LOG.WriteLine("Длина " + tableBytes.Length + tableLengthbytes.Length + " таблицы архива больше 10тб"); return; } var fullTableLengthBytes = new byte[MaxTableLengthLength]; for (int i = 0; i < tableLengthbytes.Length; i++) { fullTableLengthBytes[i] = tableLengthbytes[i]; } fileAll.Write(fullTableLengthBytes, 0, MaxTableLengthLength); fileAll.Write(tableBytes, 0, tableBytes.Length); fileAllOrigin.Seek(0, SeekOrigin.Begin); fileAllOrigin.WriteTo(fileAll); //foreach(var item in filesAndDirsRelativePaths) // ClearDirOrFile(item.Key); } }
public static KeyValuePair <long, long> Extract(this CassetteInfo cassette, string archRelativePath, string inArchivePath) { KeyValuePair <long, long> inArchivePosLength = new KeyValuePair <long, long>(); string key = cassette.cassette.Name + "/" + archRelativePath + "/" + inArchivePath; bool isOk = false; CachedArchives.Add(cassette.cassette.Name + "/" + archRelativePath, true); CachedArchives[cassette.cassette.Name + "/" + archRelativePath] = ExtractArchiveToMemory(cassette.cassette.Name, inArchivePath, cassette.url, archRelativePath); //task.GetAwaiter().OnCompleted(() => CachedArchives[cassette.Name + "/" + archRelativePath] = task.Result); //while (task.Status == TaskStatus.Running && (isOk = !CacheInArchives.TryGetValue(key, out inArchivePosLength))) //{} if (!isOk && !CacheInArchives.TryGetValue(key, out inArchivePosLength)) { LOG.WriteLine("Нет в архиве " + cassette.url + archRelativePath + " файла " + inArchivePath); throw new Exception();//return null; } return (new KeyValuePair <long, long>(inArchivePosLength.Key, inArchivePosLength.Value)); //CacheInArchives = CacheInArchives.Concat() // .ToDictionary(i => i.Key, i => i.Value); Task<bool> Tuple.Create }
/// <summary> /// Дабавляет файл, возвращает добавленные в базу данных элементы /// </summary> /// <param name="file"></param> /// <param name="collectionId"></param> /// <returns></returns> public static IEnumerable <XElement> AddFile(this Cassette cassette, FileInfo file, string collectionId) { List <XElement> addedElements = new List <XElement>(); // string smallImageFullName = null; string fname = file.FullName; XElement doc = null; // Первая задача - выделить тождественный документ, он помещается в doc // Проверка на существование документа в архиве, удовлетворяющего условиям: размер совпадает, // расширитель совпадает и байтовая последовательность также совпадает string fileSize = file.Length.ToString(); string fileExt = Path.GetExtension(fname).ToLower();//fname.Substring(fname.LastIndexOf('.')).ToLower(); // расширение вместе с точкой doc = cassette.db.Elements() .FirstOrDefault( (XElement e) => { XElement iisstore = e.Element(ONames.TagIisstore); if (iisstore == null) { return(false); } XAttribute on = iisstore.Attribute(ONames.AttOriginalname); XAttribute sz = iisstore.Attribute(ONames.AttSize); if (on == null || sz == null) { return(false); } string uri = iisstore.Attribute(ONames.AttUri).Value; if (!on.Value.ToLower().EndsWith(fileExt) || sz.Value != fileSize) { return(false); } if (File.ReadAllBytes(fname) .SequenceEqual( File.ReadAllBytes(cassette.Dir.FullName + "/" + cassette.GetOriginalDocumentPath(uri)))) { return(true); } return(false); }); bool docIsNew = (doc == null); if (docIsNew) { // Включение файла в архив string pure_fname = fname.Split(Cassette.slashes).Last(); //int p = pure_fname.LastIndexOf('.'); string ext = Path.GetExtension(pure_fname).ToLower();//(p != -1 ? pure_fname.Substring(p).ToLower() : ""); // копируем оригинал под имеющимся расширением var filepath = cassette.Dir.FullName + "/originals/" + cassette._folderNumber + "/" + cassette._documentNumber + ext; try { File.Copy(fname, filepath); } catch (Exception exc) { LOG.WriteLine("ошибка добавления документа, не послучилось скопировать в " + filepath + Environment.NewLine + exc.Message + Environment.NewLine + exc.StackTrace ); return(null); } // Надо бы эту нештатную ситуацию зафиксировать в каком-нибудь логе // Создаем запись и привязываем ее к коллекции DocType triple = Cassette.docTypes.Where(doct => doct.ext == ext || doct.ext == "unknown").First(); var ex = triple.ext; var documenttype = triple.content_type; var docTag = triple.tag; XName docId = XName.Get(cassette.Name + "_" + cassette._folderNumber + "_" + cassette._documentNumber); var iisstore = new XElement(ONames.TagIisstore, new XAttribute(ONames.AttUri, "iiss://" + cassette.Name + "@iis.nsk.su/0001/" + cassette._folderNumber + "/" + cassette._documentNumber), new XAttribute(ONames.AttOriginalname, fname), new XAttribute(ONames.AttSize, file.Length.ToString()), new XAttribute(ONames.AttDocumenttype, documenttype), new XAttribute(ONames.AttDocumentcreation, file.CreationTimeUtc.ToString("s")), new XAttribute(ONames.AttDocumentfirstuploaded, System.DateTime.Now.ToString("s")), new XAttribute(ONames.AttDocumentmodification, file.LastWriteTimeUtc.ToString("s")), new XAttribute(ONames.AttChecksum, "qwerty")); //string documentname = cassette.Name + " " + cassette._folderNumber + " " + cassette._documentNumber; //TODO: поменял концепцию формирования имени документа int lastpoint = fname.LastIndexOf('.'); int afterlastslash = Math.Max(fname.LastIndexOf('/'), fname.LastIndexOf('\\')) + 1; string documentname = cassette.DocNamePrefix + fname.Substring(afterlastslash, lastpoint > afterlastslash ? lastpoint - afterlastslash : fname.Length - afterlastslash); doc = new XElement(docTag, new XAttribute(ONames.rdfabout, docId), new XElement(ONames.TagName, documentname), new XElement(ONames.TagComment, fname), iisstore); // Дополнительная обработка для фотографий if (docTag == ONames.TagPhotodoc) { // Делаем разные копии Uri _source = cassette.MakePhotoPreviews(iisstore, "smn"); if (_source != null) { try { // Берем exif-данные Exif.ExifMetadata emeta = new Exif.ExifMetadata(_source); var dit = emeta.DateImageTaken; if (dit.HasValue) { DateTime dt = dit.Value; doc.Add( new XElement(ONames.TagFromdate, dt.ToString("s"))); } } catch (Exception exep) { Fogid.Cassettes.LOG.WriteLine(exep.Message + " Не удалось зафиксировать Exif информацию по документу " + iisstore.ToString()); } } } // Дополнительная обработка для видео if (docTag == ONames.TagVideo) { int o_width = 640; // Это значения "от фонаря" int o_height = 480; // Сначала, почитаем метаинформацию. Используется программа MediaInfo string output = ""; try { var proc = new System.Diagnostics.Process(); // Redirect the output stream of the child process. proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.FileName = App_Bin_Path + "MediaInfo.exe"; proc.StartInfo.Arguments = " --Output=XML " + cassette.Dir.FullName + "/originals/" + cassette._folderNumber + "/" + cassette._documentNumber + ext; proc.Start(); // Do not wait for the child process to exit before // reading to the end of its redirected stream. // proc.WaitForExit(); // Read the output stream first and then wait. output = proc.StandardOutput.ReadToEnd(); proc.WaitForExit(); var xoutput = XElement.Parse(output).Element("File"); string o_width_s = xoutput.Elements("track").First(tr => tr.Attribute("type").Value == "Video").Element("Width").Value; string o_height_s = xoutput.Elements("track").First(tr => tr.Attribute("type").Value == "Video").Element("Height").Value; o_width = Int32.Parse(new string(o_width_s.Where(c => c >= '0' && c <= '9').ToArray())); o_height = Int32.Parse(new string(o_height_s.Where(c => c >= '0' && c <= '9').ToArray())); // Display_aspect_ratio string o_aspect_s = xoutput.Elements("track").First(tr => tr.Attribute("type").Value == "Video").Element("Display_aspect_ratio").Value; iisstore.Add( new XAttribute("width", "" + o_width), new XAttribute("height", "" + o_height), new XAttribute("duration", xoutput.Elements("track").First(tr => tr.Attribute("type").Value == "Video").Element("Duration").Value), new XAttribute("framerate", xoutput.Elements("track").First(tr => tr.Attribute("type").Value == "Video").Element("Frame_rate").Value), o_aspect_s == "4:3" || o_aspect_s == "16:9" ? new XAttribute("aspect", o_aspect_s) : null, null); } catch (Exception exc) { LOG.WriteLine(" ошибка добавления документа, не получилось обработать видео " + output + Environment.NewLine + exc.Message + Environment.NewLine + exc.StackTrace ); } string sz = cassette.GetPreviewParameter(iisstore, "medium", "framesize"); string[] w_h = sz.Split(new char[] { 'x' }); int m_width = Int32.Parse(w_h[0]); int m_height = Int32.Parse(w_h[1]); int m_width_corrected = m_height * o_width / o_height; // Если кадр меньше запланированного, оставляем "родной" размер string output_size = m_height < o_height ? m_width_corrected + "x" + m_height : o_width + "x" + o_height; // Зафиксируем размер в iisstore if (output_size != cassette.finfo.Element("video").Element("medium").Attribute("framesize").Value) { var framesize_att = iisstore.Attribute("video.medium.framesize"); if (framesize_att == null) { iisstore.Add(new XAttribute("video.medium.framesize", "" + output_size)); } else { framesize_att.Value = "" + output_size; } } // Сформируем команду на вычисление превьюшки cassette.MakeVideoPreview(iisstore); // Зафиксируем дату съемки по LastWriteTime DateTime dt = cassette.Dir.GetFiles("originals/" + cassette._folderNumber + "/" + cassette._documentNumber + ext)[0].LastWriteTime; doc.Add(new XElement(ONames.TagFromdate, dt.ToString("s"))); } // дополнительная обработка аудио if (docTag == ONames.TagAudio) { cassette.MakeAudioPreview(iisstore); } cassette.IncrementDocumentNumber(); addedElements.Add(doc); cassette.db.Add(doc); // попытка добавить принадлежность к архиву XElement archMember = cassette.CreateArchiveMember(docId.ToString()); if (archMember != null) { addedElements.Add(archMember); cassette.db.Add(archMember); } } else { doc = XElement.Parse(doc.ToString()); doc.Add(new XAttribute("itIsCopy", "true")); addedElements.Add(doc); } string dId = doc.Attribute(ONames.rdfabout).Value; // Проверим наличие связи bool membershipExists = (!docIsNew) && //var collmem = cassette.db.Elements(ONames.TagCollectionmember) .Any(cm => cm.Element(ONames.TagCollectionitem).Attribute(ONames.rdfresource).Value == dId && cm.Element(ONames.TagIncollection).Attribute(ONames.rdfresource).Value == collectionId); // if (collmem != null) membershipExists = true; // А теперь, наконец, добавим членство в коллекции if (!membershipExists) { XElement collectionmember = new XElement(ONames.TagCollectionmember, new XAttribute(ONames.rdfabout, cassette.Name + "_" + collectionId + "_" + dId), new XElement(ONames.TagIncollection, new XAttribute(ONames.rdfresource, collectionId)), new XElement(ONames.TagCollectionitem, new XAttribute(ONames.rdfresource, dId))); addedElements.Add(collectionmember); cassette.db.Add(collectionmember); } return(addedElements); }