2011-10-27 39 views
0

我正在使用SQL數據庫將Excel文件(以及其他文件類型,如PDF)作爲二進制數據存儲。我使用下面的代碼將這些文件提取到文件系統上。從SQL DB檢索時,Excel文件已損壞

問題: PDF文件出來就好了。但對於Excel來說,文件會被創建,當我嘗試打開它們時,它們會崩潰或只是給我提供垃圾文本。

我正在使用此代碼編寫此應用程序用於檢索文件。此代碼使用OpenMcdf,我不完全理解,因爲我找不到有用的聯機文檔。

//execution starts here 
public override void SaveToDisk() 
{ 

    byte[] keys = { (byte)0xd0, (byte)0xcf }; 


    //Searches through m_RawOleObject for combination of 'keys' 
    int offset = Utils.SearchBytes(m_RawOleObject, keys); //returns '60' in case of Excel and '66' in case of Pdf 

    //m_RawOleOjbect contains the data from the sqlDataReader (the binary data from the column.) 
    m_RawOleObject = strip(m_RawOleObject, offset); 

    MemoryStream ms = new MemoryStream(m_RawOleObject); 
    CompoundFile cf = new CompoundFile(ms); 
    GetStorageByName(cf.RootStorage, m_StorageName); 

    if (Storage != null) 
    { 
     if (Storage is CFStream) 
     { 
      m_RawOleObject = (Storage as CFStream).GetData(); 
     } 
     m_filename = System.IO.Path.Combine(STOREPATH, Utils.CombineFilenameWithExtension(Filename, m_extension)); 

     WriteToFile(m_filename, m_RawOleObject); 
    } 

} 

protected void WriteToFile(string fn, byte[] obj) 
{ 
    fn = GetNextAvailableFilename(fn, 0); 
    FileStream fs = new FileStream(fn, FileMode.Create); 
    BinaryWriter writer = new BinaryWriter(fs); 
    writer.Write(obj); 
    writer.Close(); 
    fs.Close(); 
    fs.Dispose(); 
} 


protected void GetStorageByName(CFStorage cfs, string name) 
{ 
    VisitedEntryAction va = delegate(CFItem target) 
    { 
     if (target is CFStorage) 
     { 
      GetStorageByName((CFStorage)target, name); 
     } 
     else 
     { 
      if (target.Name == name) 
       Storage = target; 
     } 
    }; 

    //Visit NON-recursively (first level only) 
    cfs.VisitEntries(va, false); 
} 

任何想法這裏發生了什麼?爲什麼excel損壞?儘管經過數小時的搜索,我仍無法在網上找到很多!

任何想法,建議或解決方案將不勝感激。

感謝

+0

** **什麼數據庫和哪個版本? ** SQL **只是結構化查詢語言 - 許多**數據庫系統使用的語言 - ** SQL **是** NOT **數據庫產品......這類東西通常是**供應商 - 特定的** - 所以我們真的需要知道什麼**數據庫系統**您正在使用.... –

+0

首先猜測會是SQL Server,因爲提及SqlDataReader – sq33G

+0

好..我以爲'SQL DB'清楚地表明Microsoft SQL Server!現在是2005年 – user732528

回答

0
如下

更改SaveToDisk邏輯:

public override void SaveToDisk() 
{ 
    byte[] keys = { (byte)0xd0, (byte)0xcf, (byte)0x11, (byte)0xe0, (byte)0xa1, (byte)0xb1, (byte)0x1a, (byte)0xe1 }; 
    int offset = Utils.SearchBytes(m_RawOleObject, keys); 
    using (MemoryStream ms = new MemoryStream(strip(m_RawOleObject, offset))) 
    { 
     CompoundFile cf = new CompoundFile(ms, UpdateMode.ReadOnly, true, true); 
     m_filename = GetNextAvailableFilename(System.IO.Path.Combine(STOREPATH, Utils.CombineFilenameWithExtension(Filename, m_extension)), 0); 
     using (var fs = new FileStream(m_filename, FileMode.Create)) 
     { 
      cf.Save(fs); 
      cf.Close(); 
     } 
    } 

    //Workbook would be saved as hidden in previous step 
    Microsoft.Office.Interop.Excel.Application xlApp = null; 
    Microsoft.Office.Interop.Excel.Workbook xlWb = null; 
    try 
    { 
     xlApp = new Microsoft.Office.Interop.Excel.Application(); 
     xlWb = xlApp.Workbooks.Open(m_filename); 
     xlWb.CheckCompatibility = false; 

     foreach (Window wn in xlApp.Windows) 
     { 
      wn.Visible = true; 
     } 
     xlWb.Save(); 
     xlWb.Close(); 
    } 
    catch (Exception e) 
    { 
     //TODO: Log error and continue 
    } 
    finally 
    { 
     if (xlWb != null) 
      Marshal.ReleaseComObject(xlWb); 
     if (xlApp != null) 
      Marshal.ReleaseComObject(xlApp); 
     xlApp = null; 
    } 
}