using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Data.SqlClient; using Csla; using Csla.Data; using System.IO; using System.IO.Compression; using Volian.Base.Library; namespace VEPROMS.CSLA.Library { public delegate void ROImageInfoCompressionEvent(object sender, ROImageInfoCompressionEventArgs args); public class ROImageInfoCompressionEventArgs { private int _Total; public int Total { get { return _Total; } set { _Total = value; } } private int _Current; public int Current { get { return _Current; } set { _Current = value; } } private string _FileName; public string FileName { get { return _FileName; } set { _FileName = value; } } private ROImageCompressionEventType _Type; public ROImageCompressionEventType Type { get { return _Type; } set { _Type = value; } } public ROImageInfoCompressionEventArgs(ROImageCompressionEventType type) { _Type = type; } public ROImageInfoCompressionEventArgs(int current, string fileName) { _Current = current; _FileName = fileName; _Type = ROImageCompressionEventType.Update; } public ROImageInfoCompressionEventArgs(int total) { _Type = ROImageCompressionEventType.Initialize; _Total = total; } } public enum ROImageCompressionEventType:int {Initialize, Update, Complete}; public partial class ROImageInfo { public static event ROImageInfoCompressionEvent CompressAllExistingImages; public static void OnCompressAllExistingImages(object sender, ROImageInfoCompressionEventArgs args) { if (CompressAllExistingImages != null) CompressAllExistingImages(sender, args); } // put in for debug //public static int CacheCountPrimaryKey //{ get { return _CacheByPrimaryKey.Count; } } //public static int CacheCountList //{ get { return _CacheList.Count; } } public static ROImageInfo GetByROFstID_FileName(int rOFstID, string fileName) { //if (!CanGetObject()) // throw new System.Security.SecurityException("User not authorized to view a ROImage"); try { if (fileName.EndsWith("PCX")) fileName = fileName.Replace(".PCX", ".TIF"); ROImageInfo tmp = DataPortal.Fetch(new ROFstID_FileNameCriteria(rOFstID, fileName)); if (tmp.ErrorMessage == "No Record Found") { tmp.Dispose(); // Clean-up ROImage tmp = null; } return tmp; } catch (Exception ex) { throw new DbCslaException("Error on ROImage.GetByROFstID_FileName", ex); } } public bool ImagesZipped() { FolderInfo topFolder = FolderInfo.Get(1); FolderConfig fc = topFolder.MyConfig as FolderConfig; return fc.Images_zipped; } public static byte[] Compress(byte[] blob) { int size = blob.Length; using (MemoryStream Source = new MemoryStream(blob)) { using (MemoryStream Destination = new MemoryStream()) { using (DeflateStream Zip = new DeflateStream(Destination, CompressionMode.Compress, true)) { int bytesToRead = 0; Source.Position = 0; while (Source.Position < Source.Length) { if (Source.Length > int.MaxValue) bytesToRead = int.MaxValue; else bytesToRead = (int)(Source.Length - Source.Position); byte[] buf = new byte[bytesToRead]; Source.Read(buf, 0, bytesToRead); Zip.Write(buf, 0, bytesToRead); } Zip.Close(); } return Destination.ToArray(); } } } public static byte[] Decompress(byte[] blob, int bsize) { if (blob == null) return null; using (MemoryStream inputStream = new MemoryStream(blob)) { using (DeflateStream unzip = new DeflateStream(inputStream, CompressionMode.Decompress)) { using (BinaryReader reader = new BinaryReader(unzip)) { byte[] bytes = new byte[bsize]; reader.Read(bytes, 0, bsize); return bytes; } } } } public static void FlagImagesZipped() { using (Folder folder = Folder.Get(1)) { FolderConfig cf = folder.MyConfig as FolderConfig; cf.Images_zipped = true; folder.Config = cf.ToString(); ; folder.Save(); } } // zip all images in the database. It was decided that images would be zipped in September of 2012 // for a few reasons: 1) database size will be smaller; 2) transfer from server of images will be faster; // 3) database migration wouldn't use as much memory. // public static void ZipImages() { FolderInfo fi = FolderInfo.Get(1); FolderConfig cf = fi.MyConfig as FolderConfig; if (cf.Images_zipped) return; // put the ids in a list and process each separately because if we do it any other way, we run // into memory issues. ROImageInfoList rol = ROImageInfoList.Get(); List imageIds = new List(); foreach (ROImageInfo roi in rol) imageIds.Add(roi.ImageID); rol.Dispose(); OnCompressAllExistingImages(null, new ROImageInfoCompressionEventArgs(imageIds.Count)); int pcount = 1; foreach (int id in imageIds) { using (ROImage ro = ROImage.GetJustROImage(id))//Don't load figures or ROFST - Causing Memory Crash { string nm = ro.FileName; OnCompressAllExistingImages(null, new ROImageInfoCompressionEventArgs(pcount++, nm)); ROImageConfig rc = new ROImageConfig(); rc.Image_Size = ro.Content.Length.ToString(); ro.Content = ROImageInfo.Compress(ro.Content); ro.Config = rc.ToString(); ro.Save(); } } OnCompressAllExistingImages(null, new ROImageInfoCompressionEventArgs( ROImageCompressionEventType.Complete)); using (Folder folder = Folder.Get(1)) { cf.Images_zipped = true; folder.Config = cf.ToString(); folder.Save(); } } private void DataPortal_Fetch(ROFstID_FileNameCriteria criteria) { if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] ROImageInfo.DataPortal_Fetch", GetHashCode()); try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { ApplicationContext.LocalContext["cn"] = cn; using (SqlCommand cm = cn.CreateCommand()) { cm.CommandType = CommandType.StoredProcedure; cm.CommandText = "getROImageByROFstID_FileName"; cm.Parameters.AddWithValue("@ROFstID", criteria.ROFstID); cm.Parameters.AddWithValue("@FileName", criteria.FileName); cm.CommandTimeout = Database.DefaultTimeout; using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader())) { if (!dr.Read()) { _ErrorMessage = "No Record Found"; return; } ReadData(dr); } } // removing of item only needed for local data portal if (ApplicationContext.ExecutionLocation == ApplicationContext.ExecutionLocations.Client) ApplicationContext.LocalContext.Remove("cn"); } } catch (Exception ex) { if (_MyLog.IsErrorEnabled) _MyLog.Error("ROImageInfo.DataPortal_Fetch", ex); _ErrorMessage = ex.Message; throw new DbCslaException("ROImageInfo.DataPortal_Fetch", ex); } } [Serializable()] private class ROFstID_FileNameCriteria { private int _ROFstID; public int ROFstID { get { return _ROFstID; } } private string _FileName; public string FileName { get { return _FileName; } } public ROFstID_FileNameCriteria(int rOFstID, string fileName) { _ROFstID = rOFstID; _FileName = fileName; } } } public class ROImageFile : IDisposable { private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); #region Fields private bool _IsDisposed; //private static string _TemporaryFolder = null; #endregion #region Properties private ROImageInfo _MyROImage = null; public ROImageInfo MyROImage { get { return _MyROImage; } set { TryDelete(); _MyROImage = value; CreateFile(); } } private FileInfo _MyFile = null; public FileInfo MyFile { get { return _MyFile; } } private string _Extension = "TIF"; public string Extension { get { return _Extension; } set { _Extension = value; } } #endregion #region Private Methods private void TryDelete() { if (_MyROImage == null) return; if (_MyFile == null) return; if (_MyFile.Exists) { try { _MyFile.Delete(); } catch (IOException ex) { _MyLog.Error("TryDelete", ex); } finally { _MyFile = null; _MyROImage = null; } } } private bool _Created = false; private int _Unique = 0; private string Unique { get { string retval = ""; if (_Unique != 0) retval = "_" + _Unique.ToString(); _Unique++; return retval; } } private void CreateFile() { while (!_Created) CreateTemporaryFile(); } private void CreateTemporaryFile() { try { if (_MyROImage != null) { _MyFile = new FileInfo(string.Format(@"{0}\tmp_{1}{2}", VlnSettings.TemporaryFolder, Unique, MyROImage.FileName)); FileStream fs = _MyFile.Create(); ROImageConfig roicfg = new ROImageConfig(MyROImage); int size = Convert.ToInt32(roicfg.Image_Size); byte[] tmpb = ROImageInfo.Decompress(MyROImage.Content, size); fs.Write(tmpb, 0, tmpb.Length); fs.Close(); _MyFile.CreationTimeUtc = MyROImage.DTS; _MyFile.LastWriteTimeUtc = MyROImage.DTS; _Created = true; } } catch (Exception ex) { Console.WriteLine(ex.Message); } } public string FullName { get { return _MyFile.FullName; } set { if (FullName != value) _MyFile = new FileInfo(value); } } public void SaveFile() { if (_MyROImage == null) return; ROImage roImage = _MyROImage.Get(); FileStream fs = _MyFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite); Byte[] buf = new byte[_MyFile.Length]; fs.Read(buf, 0, buf.Length); fs.Close(); roImage.Content = buf; roImage.UserID = Volian.Base.Library.VlnSettings.UserID; roImage.DTS = _MyFile.LastWriteTimeUtc; roImage.Save(); } #endregion #region Constructors public ROImageFile(ROImageInfo myROImage) { MyROImage = myROImage; } #endregion #region Destructor ~ROImageFile() { Dispose(false); } public void Dispose() { Dispose(false); GC.SuppressFinalize(this); } protected void Dispose(bool disposing) { if (!_IsDisposed) { _IsDisposed = true; TryDelete(); } } #endregion } public partial class ROImageInfoList { public static ROImageInfoList GetByRODbIDNoData(int rODbID) { try { ROImageInfoList tmp = DataPortal.Fetch(new RODbIDNoDataCriteria(rODbID)); //ROImageInfo.AddList(tmp); tmp.AddEvents(); return tmp; } catch (Exception ex) { throw new DbCslaException("Error on ROImageInfoList.GetByRODbID", ex); } } private class RODbIDNoDataCriteria { public RODbIDNoDataCriteria(int rODbID) { _RODbID = rODbID; } private int _RODbID; public int RODbID { get { return _RODbID; } set { _RODbID = value; } } } private void DataPortal_Fetch(RODbIDNoDataCriteria criteria) { this.RaiseListChangedEvents = false; if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] ROImageInfoList.DataPortal_FetchRODbID", GetHashCode()); try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cm = cn.CreateCommand()) { cm.CommandType = CommandType.StoredProcedure; cm.CommandText = "getROImagesByRODbIDNoData"; cm.Parameters.AddWithValue("@RODbID", criteria.RODbID); cm.CommandTimeout = Database.DefaultTimeout; using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader())) { IsReadOnly = false; while (dr.Read()) this.Add(new ROImageInfo(dr)); IsReadOnly = true; } } } } catch (Exception ex) { if (_MyLog.IsErrorEnabled) _MyLog.Error("ROImageInfoList.DataPortal_FetchRODbID", ex); throw new DbCslaException("ROImageInfoList.DataPortal_Fetch", ex); } this.RaiseListChangedEvents = true; } public static ROImageInfoList GetByRODbIDFilename(int rODbID,string filename) { try { ROImageInfoList tmp = DataPortal.Fetch(new RODbIDFilenameCriteria(rODbID,filename)); //ROImageInfo.AddList(tmp); tmp.AddEvents(); return tmp; } catch (Exception ex) { throw new DbCslaException("Error on ROImageInfoList.GetByRODbIDFilename", ex); } } private class RODbIDFilenameCriteria { public RODbIDFilenameCriteria(int rODbID,string filename) { _RODbID = rODbID; _Filename = filename; } private int _RODbID; public int RODbID { get { return _RODbID; } set { _RODbID = value; } } private string _Filename; public string Filename { get { return _Filename; } set { _Filename = value; } } } private void DataPortal_Fetch(RODbIDFilenameCriteria criteria) { this.RaiseListChangedEvents = false; if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] ROImageInfoList.DataPortal_FetchRODbIDFilename", GetHashCode()); try { using (SqlConnection cn = Database.VEPROMS_SqlConnection) { using (SqlCommand cm = cn.CreateCommand()) { cm.CommandType = CommandType.StoredProcedure; cm.CommandText = "getROImagesByRODbID_Filename"; cm.Parameters.AddWithValue("@RODbID", criteria.RODbID); cm.Parameters.AddWithValue("@FileName", criteria.Filename); cm.CommandTimeout = Database.DefaultTimeout; using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader())) { IsReadOnly = false; while (dr.Read()) this.Add(new ROImageInfo(dr)); IsReadOnly = true; } } } } catch (Exception ex) { if (_MyLog.IsErrorEnabled) _MyLog.Error("ROImageInfoList.DataPortal_FetchRODbIDFilename", ex); throw new DbCslaException("ROImageInfoList.DataPortal_FetchRODbIDFilename", ex); } this.RaiseListChangedEvents = true; } } }