18

jQuery ajax呼び出しからASP.NET Web ApiからCSVファイルをダウンロードする方法に取り組んでいます。CSV ファイルは、カスタム CsvFormatter に基づいて Web API サーバーから動的に生成されます。

jQuery からの Ajax:

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

サーバーでは、EmployeeCsvFormatter次の記事から派生したものと同様に実装されています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"));
    }
    ...
}

ファイルをダウンロードする通常の方法のようにダウンロードしたいことを示すオーバーライド メソッドも追加しました (ダウンロード タブでダウンロード ファイルを確認できます)。

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

しかし、それは機能しません。Fiddler からの応答が正しいように見えますが、Chrome のステータス バーまたはダウンロード タブにダウンロード ファイルが表示されません。

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

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

私が理解していないどこかが間違っているに違いありません。通常の方法で CSV ファイルをダウンロードして動作させるにはどうすればよいですか?

4

3 に答える 3

15

Ajax のようなファイルのダウンロードを要求するための jQuery プラグインは、単純な form submit を使用してAjax なしでそれを行います。

初めの:

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

ajax スタイルのインターフェイスを備えているため、外部からこのように呼び出すことができます

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

以下を使用した別の簡単なアプローチ:

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

サーバーでは、MediaTypeMappingsもう 1 つのコンストラクターを追加して使用する必要があります。

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

次に、このフォーマッターを Web Api 構成に追加します。

   configuration.Formatters.Add(new EmployeeCsvFormatter
            (new QueryStringMapping("format", "csv", "text/csv")));
于 2013-03-11T08:48:33.550 に答える
3

別の方法として、添付ファイルで応答する API メソッドに設定された要求された URL を使用して、アンカー () またはボタンのクリックでダウンロードを提供できます。

( CsvMediaTypeFormatterSystem.Net.Http.Formatting.MediaTypeFormatter から派生) では、上記の回答に示されているように text/csv MIME タイプをマッピングすることに加えて、次のことを行う必要があることがわかりました。

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

注: ストリームを書き込むときは、Content-Lengthヘッダーを設定し、ストリームをフラッシュすることを忘れないでください。を呼び出さFlush()ないと、正しいコンテンツの長さが設定されていても、返された応答がクライアントに正常に返されないことがわかりました。

于 2014-04-04T10:21:16.570 に答える