vb.net 向客户端发送 Excel 文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13276905/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 11:03:47  来源:igfitidea点击:

Sending an Excel file to the client

asp.netvb.netexcel.net-3.5asp.net-2.0

提问by Msonic

I am trying to send an Excel file to the client of an ASP.Net web page, but it doesn't work.

我正在尝试将 Excel 文件发送到 ASP.Net 网页的客户端,但它不起作用。

When the user clicks a button, some data from our server-side database is formatted, put in an Excel file and sent to the user (as a direct download).

当用户点击一个按钮时,我们服务器端数据库中的一些数据被格式化,放入一个 Excel 文件并发送给用户(作为直接下载)。

Everything works well, except the sending part and any help would be greatly appreciated.

一切正常,除了发送部分和任何帮助将不胜感激。

Here is the code I'm using right now (client side):

这是我现在使用的代码(客户端):

var dataAjax = {};
$.ajax({
    async: false,
    type: "POST",
    url: "Default.aspx/BuildExcelFile",
    contentType: "application/json",
    data: JSON.stringify(dataAjax),
    dataType: "text",
    success: function(html) {
        //alert(html);
    },
    error: function(request, status, error) {
        alert("An error occurred : [" + error + "]");
    }

});

And the server side code:

和服务器端代码:

<WebMethod()> _
Public Shared Function BuildExcelFile() As String
    Dim localExcelPath = "C:\temp1111.xlsx"

    'Build the excel file here...
    '...

    'Delete the old version of the Excel file
    System.IO.File.Delete(localExcelPath)
    'Save the Excel File locally
    xWorkSheet.SaveAs(localExcelPath)
    xWorkBook.Close()
    exc.Quit()

    'The generated excel is valid, can be opened on the server just fine

    'Send the excel file to the client
    'This part is not working! :(
    System.Web.HttpContext.Current.Response.Clear()
    System.Web.HttpContext.Current.Response.ContentType = "MS-Excel/xls"
    System.Web.HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=" & System.IO.Path.GetFileName(localExcelPath))
    System.Web.HttpContext.Current.Response.TransmitFile(localExcelPath)
    System.Web.HttpContext.Current.Response.End()

    Return "Success"

End Function

I am getting this error when I try to verify the value of Current.Response

当我尝试验证的值时出现此错误 Current.Response

Response: Cannot refer to an instance member of a class from within a shared method or shared member initializer without an explicit instance of the class.

Also, if I remove the Response.End()call, the data is received in the html variable of the successfunction in the ajax. However, I want the file to be downloaded, not received as text...

此外,如果我删除Response.End()调用,则数据将success在 ajax 中函数的 html 变量中接收。但是,我希望文件被下载,而不是作为文本接收...

If I keep Response.End(), I get an Internal Server Error.

如果我保留 Response.End(),我会得到一个Internal Server Error.

Is it not working because my Webmethod is shared? Any clue what's going on here? What can I do to fix this problem?

是不是因为我的 Webmethod 是共享的?知道这里发生了什么吗?我能做些什么来解决这个问题?

Edit:

编辑:

I'm using .Net 3.5, if that matters

如果这很重要,我正在使用 .Net 3.5

I'm not using MVC

我没有使用 MVC

采纳答案by Yatrix

I had this exact same problem sending data from client to server as well. You could get around it by loading an iFrame dynamically that kicks off the download - the iFrame is basically just filled with a blank aspx page that starts the download in the Page_Load. You could also save the file to the server and provide a link to download it in the client. Those are the workarounds I found that worked.

我也遇到了从客户端向服务器发送数据的完全相同的问题。您可以通过动态加载启动下载的 iFrame 来绕过它 - iFrame 基本上只是填充了一个空白的 aspx 页面,该页面在Page_Load. 您还可以将文件保存到服务器并提供一个链接以在客户端中下载它。这些是我发现有效的解决方法。

I don't know if you can do it the way you're trying or not. I checked examples all over and it never worked. If you can't figure it out, these ways worked for me.

我不知道你是否可以按照你正在尝试的方式做到这一点。我检查了所有示例,但从未奏效。如果你想不通,这些方法对我有用。

回答by Anand

Public Shared Function BuildExcelFile() As String
    Dim localExcelPath = "C:\temp1111.xlsx"

    'Build the excel file here...
    '...
    xWorkSheet.SaveAs(localExcelPath)
    xWorkBook.Close()
    exc.Quit()

    'The generated excel is valid, can be opened on the server just fine

    'Send the excel file to the client
    'This part is not working! :(
    System.Web.HttpContext.Current.Response.Clear()
    System.Web.HttpContext.Current.Response.ContentType = "MS-Excel/xls"
    System.Web.HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=" & System.IO.Path.GetFileName(localExcelPath))
    System.Web.HttpContext.Current.Response.TransmitFile(localExcelPath)
    System.IO.File.Delete(localExcelPath)

    System.Web.HttpContext.Current.Response.End()

    Return "Success"
End Function
  1. Use postbacktrigger on your button click if you are using Ajax
  1. 如果您使用 Ajax,请在您的按钮单击上使用 postbacktrigger

回答by leviathon

This works for me:

这对我有用:

string fileName = "ExampleFileName.xlsx";
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment;  filename=" + fileName);
Response.BinaryWrite(excelPackage.GetAsByteArray());
// Response.End(); Replaced with below 3 lines to avoid ThreadAbortException
Response.Flush(); // Sends all currently buffered output to the client.
Response.SuppressContent = true;  // Gets or sets a value indicating whether to send HTTP content to the client.
ApplicationInstance.CompleteRequest(); // Causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution and directly execute the EndRequest event.

I am using a dll called 'EPPlus.dll' as my Excel library. There is no need for an Ajax call as you can instantiate the download from an Asp.net button, or simply call a method from your server-side code when you want to start the download.

我正在使用一个名为“EPPlus.dll”的 dll 作为我的 Excel 库。不需要 Ajax 调用,因为您可以从 Asp.net 按钮实例化下载,或者在您想要开始下载时简单地从服务器端代码调用一个方法。