Vraag Hoe CSV-bestand te downloaden van ASP.NET Web Api met jQuery Ajax-oproep


Ik ben bezig met het downloaden van CSV-bestanden van ASP.NET Web Api vanuit jQuery ajax-aanroep. Het CSV-bestand wordt dynamisch gegenereerd op basis van de Web API-server op basis van de aangepaste CsvFormatter.

Ajax van jQuery:

   $.ajax({
        type: "GET",
        headers: {
            Accept: "text/csv; charset=utf-8",
        },
        url: "/api/employees",
        success: function (data) {
        }
    });

Op de server, de EmployeeCsvFormatter is geïmplementeerd vergelijkbaar met onderstaande artikel, afgeleid van BufferedMediaTypeFormatter:

http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters

public class EmployeeCsvFormatter : BufferedMediaTypeFormatter
{
    public EmployeeCsvFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));
    }
    ...
}

Ik heb ook de overschrijfmethode toegevoegd om aan te geven dat ik zou willen downloaden zoals de normale manier om het bestand te downloaden (kan het downloadbestand op het downloadtabblad zien):

 public override void SetDefaultContentHeaders(Type type, 
    HttpContentHeaders headers, MediaTypeHeaderValue mediaType)       
{
    base.SetDefaultContentHeaders(type, headers, mediaType);
    headers.Add("Content-Disposition", "attachment; filename=yourname.csv");
    headers.ContentType =  new MediaTypeHeaderValue("application/octet-stream");
}

Maar het werkt niet, het downloadbestand wordt niet weergegeven in de statusbalk of in het downloadtabblad in Chrome, hoewel ik van Fiddler zie dat het antwoord correct lijkt:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/11.0.0.0
Date: Mon, 11 Mar 2013 08:19:35 GMT
X-AspNet-Version: 4.0.30319
Content-Disposition: attachment; filename=yourname.csv
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: application/octet-stream
Content-Length: 26
Connection: Close

1,Cuong,123
1,Trung,123

Mijn methode van ApiController:

public EmployeeDto[] Get()
{
    var result = new[]
               {
                   new EmployeeDto() {Id = 1, Name = "Cuong", Address = "123"},
                   new EmployeeDto() {Id = 1, Name = "Trung", Address = "123"},
               };

    return result;
}

Het moet ergens verkeerd zijn wat ik nog niet heb uitgedacht. Hoe kan ik het laten werken door CSV-bestanden op de normale manier te downloaden?


17
2018-03-11 08:40


oorsprong


antwoorden:


jQuery-plug-in voor het aanvragen van Ajax-achtige bestandsdownloads doet het zonder Ajax met behulp van een eenvoudig formulier in te dienen.

intern:

jQuery('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>')
    .appendTo('body').submit().remove()

Het heeft een ajax-achtige interface, dus van buiten kun je het zo noemen

$.download('/api/employees','format=csv');

Nog een eenvoudige benadering met behulp van:

$('#btnDownload').click(function (e) {
    e.preventDefault();
    window.location = "/api/employees?format=csv";
});

Op de server, MediaTypeMappings moet worden gebruikt door nog een constructor toe te voegen:

    public EmployeeCsvFormatter(MediaTypeMapping mediaTypeMapping)
        : this()
    {
        MediaTypeMappings.Add(mediaTypeMapping);
    }

Voeg vervolgens deze formatter toe aan de Web Api-configuratie:

   configuration.Formatters.Add(new EmployeeCsvFormatter
            (new QueryStringMapping("format", "csv", "text/csv")));

15
2018-03-11 08:48



Als een alternatieve benadering kan men de download aanbieden door te klikken op een anker () of knop met de gevraagde URL ingesteld op de API-methode die reageert met de bijlage.

In de CsvMediaTypeFormatter (Afgeleid van System.Net.Http.Formatting.MediaTypeFormatter), naast het toewijzen van het tekst / csv-MIME-type zoals weergegeven in de bovenstaande antwoorden, vond ik dat het volgende moet worden gedaan:

public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
        {
            base.SetDefaultContentHeaders(type, headers, mediaType);
            headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileName = string.Concat("data", DateTime.UtcNow.ToString("yyyyMMddhhmmss"), ".csv")
            };

            headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        }

Opmerking: bij het schrijven van de stream, stelt u de Content-Length header en vergeet niet om de stream te spoelen. Ik vond dat zonder een oproep aan Flush(), de geretourneerde reactie haalt het niet met succes terug naar de client, zelfs niet als de juiste lengte van de inhoud is ingesteld.


3
2018-04-04 10:21



U kunt de verzoekheader ook vóór verzenden instellen door de xhr te wijzigen.

    $.ajax({
    url: "/api/employees",
    type: "GET",
    beforeSend: function (xhr) {
        xhr.setRequestHeader("Accept", "text/csv");
    },
    success: function (data) {
            }
    });

1
2018-06-05 20:34