2013-03-11 42 views
16

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

のAjax:サーバで

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

EmployeeCsvFormatterBufferedMediaTypeFormatterに由来する以下の記事と同様の実装されている:

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

しかし、それは動作しません、ダウンロードファイルはフィドラーから、私は応答が正しいと思われるそれを見ていても、ステータスバーにや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ファイルをダウンロードして、どのように動作させることができますか?

+2

はAJAXでダウンロードできません。サーバーを強制的にダウンロードする場合は、現在のページを残さないように、ユーザーをurl 'window.location = url'にリダイレクトします。 – charlietfl

+0

@charlietfl:この方法でAcceptヘッダーを設定するにはどうすればよいですか? –

+0

'accept header'で何を期待していますか?ユーザーが何かを受け入れるように強制できない – charlietfl

答えて

15

jQuery Plugin for Requesting Ajax-like File Downloads Ajaxなしの場合using a simple form submit内部

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

の場合:あなたはこの

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

のように使用して別の簡単なアプローチを呼び出すことができ、外部からのように、それは、Ajaxスタイルのインターフェースを持っている

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

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

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

、ウェブAPI設定にこのフォーマッタを追加します。

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

この方法でAcceptヘッダーを追加するにはどうすればよいですか? –

+0

良い点。ブラウザは1つを追加します、私は恐れる。 '$ .download( '/ api/employees /'、 'format')のようにURLに書式を入れることができます。 = csv ');' – flup

+3

ああ、それは箱の中で動く?時には人生は恐怖よりも複雑ではありません!答えを更新します。 – flup

1

また、XHRを変更することによって、beforeSendでリクエストヘッダを設定することができます。別のアプローチとして、

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

、一つはURLとアンカーのクリック()またはボタンでのダウンロードを提供することができます添付ファイルで応答APIメソッドに設定を要請しました。

CsvMediaTypeFormatter(System.Net.Http.Formattingから派生。

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

注:MediaTypeFormatter)、上記の回答に示すように、テキスト/ CSV形式のMIMEタイプをマッピングすることに加えて、私は、次を実行する必要が見つかったストリームを書き込む場合、Content-Lengthヘッダを設定することを忘れストリームをフラッシュします。 Flush()への呼び出しがなければ、正しいコンテンツの長さが設定されていても、返された応答はクライアントに正常に返されません。

関連する問題