从SQL DB检索时,Excel文件已损坏

时间:2011-10-27 20:35:17

标签: c# sql-server-2005 oledb ole excel-2010

我正在使用一个SQL DB,它将Excel文件(以及其他文件类型,如PDF)存储为二进制数据。我使用以下代码将这些文件解压缩到文件系统中。

问题: 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损坏了?尽管经过数小时的搜索,我在网上找不到很多东西!

任何想法,建议或解决方案都将受到赞赏。

由于

1 个答案:

答案 0 :(得分: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;
    }
}