如何将Excel文件下载到用户的下载文件夹?

时间:2016-08-02 20:36:24

标签: c# asp.net excel telerik office-interop

在C#,asp.net 4.0项目中,我使用Microsoft.Office.Interop.Excel创建了一个Excel文件。文件正确创建并放在服务器上的文件夹中。但是,我一直无法想出一种向客户端显示文件的方法。有人能帮助我吗?

一些背景知识:我正在尝试解决阻止Excel文件打开的Microsoft更改。我们的Web应用程序使用Telerik网格,并使用ExportToExcel函数将网格导出到Excel文件。文件下载(转到用户的下载文件),但是当用户尝试打开它时,它们会得到一个空白的Excel应用程序。有一些解决方法,例如卸载创建此问题的补丁,关闭Excel安全选项,以及单击文件属性中的取消阻止;但是,我们的客户并不想做任何这些。所以我改写40多个网格的出口。

我从radGrid获取数据到数据表并使用以下代码将其写入Excel:

            Microsoft.Office.Interop.Excel.Application m_objExcel = null;
            Microsoft.Office.Interop.Excel.Workbooks m_objBooks = null;
            Microsoft.Office.Interop.Excel._Workbook m_objBook = null;
            Microsoft.Office.Interop.Excel.Sheets m_objSheets = null;
            Microsoft.Office.Interop.Excel._Worksheet m_objSheet = null;
            object m_objOpt = System.Reflection.Missing.Value;

            m_objExcel = new Microsoft.Office.Interop.Excel.Application();
            m_objBooks = (Microsoft.Office.Interop.Excel.Workbooks)m_objExcel.Workbooks;
            m_objBook = (Microsoft.Office.Interop.Excel._Workbook)(m_objBooks.Add(m_objOpt));

            m_objSheets = (Microsoft.Office.Interop.Excel.Sheets)m_objBook.Worksheets;
            m_objSheet = (Microsoft.Office.Interop.Excel._Worksheet)(m_objSheets.get_Item(1));

            int colcount = 1;
            foreach (DataColumn col in dt.Columns)
            {
                m_objSheet.Cells[1, colcount] = col.ColumnName;
                colcount++;
            }

            int rowcount = 2;
            foreach (DataRow row in dt.Rows)
            {
                for (int i = 1; i < dt.Columns.Count; i++)
                {
                    m_objSheet.Cells[rowcount, i] = row[i - 1].ToString();
                }
                rowcount++;
            }

            string currentDateTime = DateTime.Now.ToString("yyyyMMddHHmmss");

            m_objBook.SaveAs("C:\\Temp\\MD" + currentDateTime + ".xlsx");
            m_objBook.Close();

            m_objExcel.DisplayAlerts = false;
            m_objExcel.Quit();

当我尝试让用户下载文件时出现问题。我尝试了下面的代码,但是我收到错误说&#34;该进程无法访问文件&#39; C:\ Temp \ MD20160802161458.xlsx&#39;因为它正被另一个进程使用。&#34;任何人都可以解释如何在Excel创建文件之后取消阻止该文件,或者向我展示另一种将文件下载到用户的方法吗?

 string fileName = "C:\\Temp\\MD" + currentDateTime + ".xlsx", myStringWebResource = null;
 WebClient myWebClient = new WebClient();
 myStringWebResource = fileName;
 myWebClient.DownloadFile(myStringWebResource, fileName);

我还尝试了下面的代码来打开Excel文件。该文件是在服务器上创建的,但它永远不会打开。当我尝试在服务器上打开文件时,Excel崩溃。我怀疑这是因为我在我的开发机器上安装了Excel 2013,而Excel 2007在服务器上。这引发了另一个问题,因为我无法保证最终生产服务器上的Excel版本。任何建议将不胜感激。

            var excelApp = new Microsoft.Office.Interop.Excel.Application();
            excelApp.Visible = true;
            excelApp.Workbooks.Open("C:\\Temp\\MD" + currentDateTime + ".xlsx");
            m_objExcel.Quit();

2 个答案:

答案 0 :(得分:1)

关注DVK的回答,我只有使用Excel互操作的问题,但如果您不需要生成较旧的.XLS文件,并且.XLSX文件很好,我建议使用OpenXML SDK(其自由)。在线使用它生成Excel工作簿有很多例子。这是一个:

http://www.codeproject.com/Articles/670141/Read-and-Write-Microsoft-Excel-with-Open-XML-SDK

答案 1 :(得分:0)

要检查的第一件事是Excel进程是否仍在服务器上运行。 Microsoft强烈建议不要在生产服务器环境中使用Microsoft Interop组件,原因有很多。他们从来没有为此目的。这是我能够(快速)找到的最新文章:

https://support.microsoft.com/en-us/kb/257757

  

Microsoft目前不建议也不支持从任何无人参与的非交互式客户端应用程序或组件(包括ASP,ASP.NET,DCOM和NT服务)自动化Microsoft Office应用程序,因为Office可能会出现不稳定Office在此环境中运行时的行为和/或死锁。

我已经多次尝试过这条路线(由于客户的要求),但都导致了问题。其中最大的一点是Excel互操作组件有一个非常讨厌的习惯,即不会终止Excel进程,这意味着当您尝试打开文件并将其发送到客户端时,Excel可能仍会打开您的文件。解决方法是(逐字地)编写枚举计算机上正在运行的进程的代码并关闭Excel的任何实例,但当然您将面临关闭正在执行实际工作的实例的风险。

有许多经济实惠的组件可以更加可靠地运行(例如ComponentPro - 与他们没有任何关系,但我已经在很多场合使用过它们的组件)并且可以轻松实现。

编辑 - 如果必须使用互操作并强制Excel关闭

This StackOverflow article有很多不同的机制。根据您的具体操作,您可能需要尝试多条路线。释放COM对象对我来说似乎是最干净的。