web-dev-qa-db-ja.com

ajaxリクエストを使用してファイルをダウンロードする方法がないのはなぜですか?

このアプリケーションでは、次のシナリオを実装する必要があります。

  1. クライアントからリクエストが送信されます
  2. サーバーはリクエストを処理し、ファイルを生成します
  3. サーバーは応答でファイルを返します
  4. クライアントブラウザにファイルダウンロードのポップアップダイアログが表示され、ユーザーはファイルをダウンロードできます

私たちのアプリケーションはajaxベースのアプリケーションですので、ajaxリクエストを送信することは非常に簡単で便利です(jquery.ajax()関数を使用するなど)。

しかし、googilngの後、非ajax POSTリクエスト( this Popular SO thread )。したがって、ネストされた隠しフィールドを使用してformのHTML構造を構築する必要がある、い、より複雑なソリューションを実装する必要がありました。

誰かが簡単な言葉で説明して、なぜファイルをダウンロードするためにajaxリクエストを使用できないのですか?その背後にあるメカニズムは何ですか?

46
Piotr Sobczyk

AJAXについてではありません。もちろん、AJAXでファイルをダウンロードできます。ただし、ファイルはメモリに保持されます。つまり、ファイルをディスクに保存することはできません。これは、JavaScriptがディスクと対話できないためです。これは重大なセキュリティ問題となり、すべての主要なブラウザでブロックされます。

59
freakish

これは、Blobと呼ばれる新しいHTML5機能を使用して実行できます。その機能の上にラッパーとして利用できるライブラリ FileSaver.js があります。

3

それは私が二日前に自分自身に尋ねたのと同じ質問です。クライアントがExtJSを使用して記述されたプロジェクトがあり、サーバー側の実現はASP.Netで行われました。サーバー側をJavaに変換する必要があります。サーバーがクライアントからのAjax要求後に生成するXMLファイルをダウンロードする機能がありました。 Ajaxリクエスト後にファイルをダウンロードすることは不可能であり、メモリに保存することは不可能であることは誰もが知っています。しかし...元のアプリケーションブラウザでは、オプションを開いて保存し、ダウンロードをキャンセルする通常のダイアログが表示されます。 ASP.Netが何らかの形で標準の動作を変更しました...再度証明するには2日かかります-通常の方法でファイルをダウンロードする方法はありません...唯一の例外はASP.Net ...ここにASP.Netがありますコード

public static void WriteFileToResponse(byte[] fileData, string fileName)
    {
        var response = HttpContext.Current.Response;

        var returnFilename = Path.GetFileName(fileName);
        var headerValue = String.Format("attachment; filename={0}", 
            HttpUtility.UrlPathEncode(
                String.IsNullOrEmpty(returnFilename) 
                    ? "attachment" : returnFilename));
        response.AddHeader("content-disposition", headerValue);
        response.ContentType = "application/octet-stream";
        response.AddHeader("Pragma", "public");

        var utf8 = Encoding.UTF8;
        response.Charset = utf8.HeaderName;
        response.ContentEncoding = utf8;
        response.Flush();
        response.BinaryWrite(fileData);
        response.Flush();
        response.Close();
    }

このメソッドはWebMethodから呼び出され、WebMethodはExtJS.Ajax.requestから呼び出されました。それが魔法です。私にとっては、サーブレットと非表示のiframeで終わりました...

1
bes67