【问题标题】:Download excel file from page via WebApi call通过 WebApi 调用从页面下载 excel 文件
【发布时间】:2013-02-12 11:48:25
【问题描述】:

我正在尝试发送一个 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……

【问题讨论】:

  • 你怎么称呼你的方法?不起作用是什么意思?你在 fiddler/firebug/devconsole 中检查过响应的样子吗?
  • 是否需要返回 HttpResponseMessage ,可以不用stream吗?
  • 您是否尝试将 excel 文件发送到页面以便用户下载?

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


【解决方案1】:

也可用作 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】:

    我必须做一些小改动才能让它工作

    首先:将方法改为post

    [AcceptVerbs("POST")]
    

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

    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 文件。

    【讨论】:

    • 在您的 Web API 代码中,MediaTypeHeaderValue 不应该是 application/vnd.ms-excel 吗?
    • mishrsud.. 我试过了.. 当您从 javascript 拨打电话时.. 它是什么媒体类型并不重要,javascript 根本不知道如何处理它。您必须告诉浏览器您正在接受该文件,浏览器会知道它是否可以下载。我尝试了各种类型的格式,直到您明确提交或更改 window.location 以指向文件 url,它才起作用。
    【解决方案3】:

    我遇到了同样的问题。 问题解决如下:

    window.open(url)

    【讨论】:

      【解决方案4】:

      它将创建的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>
      

      【讨论】:

      • “ExportDataSetToExcel()”在哪里,它的返回类型是什么?
      【解决方案5】:

      对于.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;
                  }
              }
      

      【讨论】:

        【解决方案6】:

        当您单击特定按钮时,这将返回一个文件

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

        【讨论】:

        • FileResult 用于 MVC,而不是 WebAPI,所以不幸的是,这不是我想要的。
        • 对不起,我会看看 WebAPI 中是否有等价物
        猜你喜欢
        • 2012-08-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-02
        • 2017-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多