2013-02-12 13 views
17

Próbuję wysłać plik 9MB .xls jako odpowiedź z metody kontrolera web api. Użytkownik kliknie przycisk na stronie, co spowoduje pobranie przez przeglądarkę.Pobierz plik excela ze strony za pośrednictwem wywołania WebApi

Oto, co mam do tej pory, ale to nie działa, ale nie rzuca żadnych wyjątków.

[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); 
    } 
} 

Oto wywołanie ajax jquery coffeescript/javascript z kliknięcia przycisku w interfejsie.

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

Teraz, gdy o tym myślę chyba dataType jest złe i nie powinno być json ...

+3

Jak można nazwać metoda? Co to znaczy, że nie działa? Czy sprawdziłeś w skrzypce/firebug/devconsole jak wygląda odpowiedź? – nemesv

+0

czy konieczne jest zwrócenie HttpResponseMessage, czy nie możesz użyć strumienia? – Popeye

+0

Czy próbujesz wysłać plik Excela na stronę, aby użytkownik mógł go pobrać? – Robert

Odpowiedz

12

musiałem zrobić kilka drobnych zmian, aby to zadziałało

Pierwszy : Zmiana metody do postu

[AcceptVerbs("POST")] 

po drugie: zmiana z użyciem ajax jQuery lib używać ukrytą formę, oto moja funkcja serwisowa za to ukrytą formę i złożenie go.

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() 

Mamy nadzieję, że jest to lepszy sposób, ale na razie działa i ładnie ładuje plik Excela.

+0

W swoim kodzie Web API, czy nazwa MediaTypeHeaderValue nie powinna być aplikacją/vnd.ms-excel? – dotnetguy

+0

mishrsud .. próbowałem, że .. kiedy wykonujesz wywołanie z javascript .. nie ma znaczenia jaki to typ mediów, javascript po prostu nie wie, co z nim zrobić. Musisz poinformować przeglądarkę, że akceptujesz plik, a przeglądarka będzie wiedziała, czy może pobrać coś, czy nie. Próbowałem różnych typów formatowania i nie działa, dopóki jawnie nie przesłać lub zmienić window.location, aby wskazać adres URL pliku. – sksallaj

-2

Ten plik powróci po kliknięciu konkretnego przycisku

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

FileResult jest dla MVC, a nie WebAPI, więc nie do końca tego, czego szukam niestety. – Neil

+0

Przykro mi, zobaczę, czy w WebAPI jest odpowiednik – Robert

4

działa również jako metody HTTP GET, ale nie używać $ ajax, zamiast używać window.open (URL);

C# Kod:

[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; 
    } 

kod JS:

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

przeżyłem ten sam problem. Problem rozwiązany z następujących czynności:

window.open(url)

Powiązane problemy