通过Web Api调用从页面下载excel文件

时间:2013-02-12 11:48:26

标签: c# asp.net excel asp.net-web-api xls

我正在尝试发送一个9MB .xls文件作为web api控制器方法的响应。用户将单击页面上的按钮,这将通过浏览器触发下载。

这是我到目前为止所得到的但不起作用,但它也没有引起任何例外。

[AcceptVerbs("GET")]
public HttpResponseMessage ExportXls()
{
    try
    {
        byte[] excelData = m_toolsService.ExportToExcelFile();

        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        var stream = new MemoryStream(excelData);
        result.Content = new StreamContent(stream);
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
        {
            FileName = "Data.xls"
        };
        return result;
    }
    catch (Exception ex)
    {
        m_logger.ErrorException("Exception exporting as excel file: ", ex);
        return Request.CreateResponse(HttpStatusCode.InternalServerError);
    }
}

以下是界面中点击按钮的coffeescript / javascript jquery ajax调用。

$.ajax(
    url: route
    dataType: 'json'
    type: 'GET'
    success: successCallback
    error: errorCallback 
    )

现在我想到它可能是dataType错了,不应该是json ......

6 个答案:

答案 0 :(得分:12)

我必须进行一些小改动才能让它发挥作用

首先:将方法更改为帖子

[AcceptVerbs("POST")]

第二:从使用jQuery ajax lib改为使用隐藏表单,这是我的服务函数,用于执行隐藏表单并提交它。

exportExcel: (successCallback) =>
    if $('#hidden-excel-form').length < 1
        $('<form>').attr(
            method: 'POST',
            id: 'hidden-excel-form',
            action: 'api/tools/exportXls'
        ).appendTo('body');

    $('#hidden-excel-form').bind("submit", successCallback)
    $('#hidden-excel-form').submit()

希望有更好的方法可以做到这一点,但目前它正在工作并很好地下载excel文件。

答案 1 :(得分:10)

也可以作为HTTP GET方法,但不要使用$ ajax,而是使用 window.open(URL);

C#代码:

    [HttpGet]
    [Route("report/{scheduleId:int}")]
    public HttpResponseMessage DownloadReport(int scheduleId)
    {
        var reportStream = GenerateExcelReport(scheduleId);
        var result = Request.CreateResponse(HttpStatusCode.OK);

        result.Content = new StreamContent(reportStream);
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
        {
            FileName = "Schedule Report.xlsx"
        };

        return result;
    }

JS代码:

downloadScheduleReport: function (scheduleId) {
    var url = baseUrl + 'api/Tracker/report/' + scheduleId;
    window.open(url);
}

答案 2 :(得分:1)

我遇到了同样的问题。 问题通过以下方式解决:

window.open(url)

答案 3 :(得分:0)

它将存储在系统文件夹中创建的excel文件,并将其发送到浏览器后,将其删除。

     //path to store Excel file temporarily
     string tempPathExcelFile = AppDomain.CurrentDomain.BaseDirectory + DateTime.Now.Hour + DateTime.Now.Minute +
                          DateTime.Now.Second + DateTime.Now.Millisecond +
                          "_temp";
        try
        {
            //Get Excel using  Microsoft.Office.Interop.Excel;
            Excel.Workbook workbook = ExportDataSetToExcel();
            workbook.SaveAs(tempPathExcelFile, workbook.FileFormat);
            tempPathExcelFile = workbook.FullName;
            workbook.Close();
            byte[] fileBook = File.ReadAllBytes(tempPathExcelFile);
            MemoryStream stream = new MemoryStream();
            string excelBase64String = Convert.ToBase64String(fileBook);
            StreamWriter excelWriter = new StreamWriter(stream);
            excelWriter.Write(excelBase64String);
            excelWriter.Flush();
            stream.Position = 0;
            HttpResponseMessage httpResponseMessage = new HttpResponseMessage();
            httpResponseMessage.Content = new StreamContent(stream);
            httpResponseMessage.Content.Headers.Add("x-filename", "ExcelReport.xlsx");
            httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.ms-excel");
            httpResponseMessage.Content.Headers.ContentDisposition =
                new ContentDispositionHeaderValue("attachment");
            httpResponseMessage.Content.Headers.ContentDisposition.FileName = "ExcelReport.xlsx";
            httpResponseMessage.StatusCode = HttpStatusCode.OK;
            return httpResponseMessage;

        }
        catch (Exception ex)
        {
            _logger.ErrorException(errorMessage, ex);
            return ReturnError(ErrorType.Error, errorMessage);
        }
        finally
        {
            if (File.Exists(tempPathExcelFile))
            {
                File.Delete(tempPathExcelFile);
            }
        }

      //Javascript Code
      $.ajax({
                    url:  "/api/exportReport",
                    type: 'GET',
                    headers: {
                        Accept: "application/vnd.ms-excel; base64",
                    },
                    success: function (data) {   
                        var uri = 'data:application/vnd.ms-excel;base64,' + data;
                        var link = document.createElement("a");    
                        link.href = uri;
                        link.style = "visibility:hidden";
                        link.download = "ExcelReport.xlsx";
                        document.body.appendChild(link);
                        link.click();
                        document.body.removeChild(link);                        
                    },
                    error: function () {
                        console.log('error Occured while Downloading CSV file.');
                    },
                }); 
    In the end create an empty anchor tag at the end of your html file. <a></a>

答案 4 :(得分:0)

对于.NetCore,您只需将类型返回为文件即可。

public IActionResult ExportAsExcel()
        {
            try
            {
                using (var ms = new MemoryStream())
                {
                    var data = ExportData(); // Note: This Should be DataTable
                    data.ConvertAsStream(ms);
                    ms.Position = 0;
                    return File(ms.ToArray(), "application/octet-stream", "ExcelReport.xlsx");
                }
               
               
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message, e);
                throw;
            }
        }

答案 5 :(得分:-4)

单击特定按钮时将返回文件

 public FileResult ExportXls(){
     //the byte stream is the file you want to return
     return File(bytes, "application/msexcel")
     }