从 aspx 网页打开或下载 excel 文件失败:它没有在应用程序中打开

Opening or downloading an excel file from aspx web page fails: It doesn't open in application

我们有一个解决方案,可以将基于 ActiveReport 的报表转换为 Excel 文件。基本上这工作得很好,但在某些环境中由于一些非常奇怪的原因 Excel 文件的下载没有开始并且 Excel 文件在网络浏览器 window 上打开而不是询问如果用户想要打开或保存生成的 Excel 文件。

我们的应用程序 运行 在基于 Windows Server 2019 的虚拟机上。但是,如果我从其他计算机连接到该虚拟机上的 Web 服务器并打开相同的应用程序并将相同的报告导出到 Excel 文件中,一切正常。 Web 浏览器询问我是否要保存或打开 Excel 文档,我可以打开 Excel 或 Excel 查看器。

更奇怪的是,这个问题并没有出现在每个服务器运行同一个应用程序中。看起来,如果服务器上只安装了 Microsoft Office Excel 查看器,则会出现这些问题 - 但并非在所有情况下都是如此。如果安装完整版Excel,似乎没有问题。

我们已经尝试了我们发现的一切。我们已经设置了浏览器标志 ( https://docs.microsoft.com/en-US/troubleshoot/browsers/how-to-set-ie-to-open-office-documents-in-office-program and https://www.thewindowsclub.com/make-internet-explorer-open-linked-office-documents-in-the-appropriate-office-program ) 并浏览了数十个网页并重新安装了 Excel Viewer。

不过,这个问题似乎与浏览器标志根本无关,因为这在其他服务器上工作正常,即使浏览器标志值未在注册表项中设置。

所以,对我来说,问题似乎出在服务器上的网络浏览器设置中。我只是无法想象在哪里。服务器上安装的浏览器是IE 11.

非常感谢任何帮助。

编辑:

正如我在评论中所解释的那样,我发现,出现此问题的应用程序版本存在差异。

版本之间的差异是:

public static void ReportExport(DataDynamics.ActiveReports.Document.Document doc, 
                ReportExportOptions exportOptions, string exppath, 
                MemoryStream expstream, HttpResponse resp)
{
// For exporting to Response
string contenttype = "";

contenttype = "application/vnd.ms-excel";

// Current version, working.
// Write to Response 

    if (resp != null)
    {
        resp.Clear();
        resp.Charset = "";
        resp.ContentType = contenttype;
        byte[] expArray = expstream.ToArray();
        if (exportOptions.ExportFormat == ReportExportOptions.ExportType.Xls)
        {
            resp.AddHeader("content-disposition", "attachment; filename=\"ExcePreview.xls\"");
            resp.AppendHeader("content-length", expArray.Length.ToString());
            resp.Buffer = true;
        }
        expstream.Position = 0;
        resp.BinaryWrite(expArray);

        resp.OutputStream.Flush();
        resp.OutputStream.Close();
        resp.Flush();
        resp.Close();

        resp.End();
    }

// Previous version, not working
// Write to Response 


    if (resp != null)
    {
        resp.Clear();
        resp.Charset = "";
        resp.ContentType = contenttype;
        expstream.Position = 0;
        resp.BinaryWrite(expstream.ToArray());

        resp.End();
    }

}

编辑 2: 我在安装了 Microsoft Excel 2016 和 Microsoft Office Excel Viewer 的服务器上对此进行了测试。该服务器上还安装了导出 Excel 文件的网页。我测试的应用程序使用了这种内容类型设置:

// Previous version, not working
// Write to Response 


    if (resp != null)
    {
        resp.Clear();
        resp.Charset = "";
        resp.ContentType = contenttype;
        expstream.Position = 0;
        resp.BinaryWrite(expstream.ToArray());

        resp.End();
    }

首先,安装 Excel 时,Excel-export 工作正常。当我选择“打开”时,Excel 2016 使用导出的 Excel 文件打开。

然后我卸载了Excel。相同的 Excel-export 行为与本案例开头解释的一样:Excel 查看器未打开,Excel 'file' 在浏览器 window 上打开.

能解释清楚的人将获得奖励。

关于您的第一次编辑,重要的是 Content-Disposition header。工作版本将此 header 设置为 attachment。这告诉浏览器该文件是某种下载文件,应该用另一个程序打开或保存。此外,它将文件名设置为 'ExcePreview.xls'。 如果不设置 Content-Disposition 默认值是 inline 告诉浏览器,内容是一个网页或者应该显示在网页中。正如我们在您的第一个屏幕截图中看到的那样,文件名保持 ExcelPreview.aspx。 某些系统可能会考虑 Content-Type header,忽略 aspx 扩展名,嗅探内容并将响应视为下载的 excel 文件,但不能保证这会起作用。