1. ホーム
  2. c#

[解決済み] AngularJSを使ったASP.NET Web APIメソッドからのファイルダウンロード

2022-06-30 18:09:34

質問

Angular JSのプロジェクトで、私は <a> アンカータグがあり、クリックされると HTTP GET リクエストを行い、ファイルを返す WebAPI メソッドを作成します。

さて、私はリクエストが成功したら、ファイルをユーザーにダウンロードさせたいと思います。どうすればよいのでしょうか?

アンカータグです。

<a href="#" ng-click="getthefile()">Download img</a>

AngularJSです。

$scope.getthefile = function () {        
    $http({
        method: 'GET',
        cache: false,
        url: $scope.appPath + 'CourseRegConfirm/getfile',            
        headers: {
            'Content-Type': 'application/json; charset=utf-8'
        }
    }).success(function (data, status) {
        console.log(data); // Displays text data if the file is a text file, binary if it's an image            
        // What should I write here to download the file I receive from the WebAPI method?
    }).error(function (data, status) {
        // ...
    });
}

私のWebAPIメソッドです。

[Authorize]
[Route("getfile")]
public HttpResponseMessage GetTestFile()
{
    HttpResponseMessage result = null;
    var localFilePath = HttpContext.Current.Server.MapPath("~/timetable.jpg");

    if (!File.Exists(localFilePath))
    {
        result = Request.CreateResponse(HttpStatusCode.Gone);
    }
    else
    {
        // Serve the file to the client
        result = Request.CreateResponse(HttpStatusCode.OK);
        result.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
        result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
        result.Content.Headers.ContentDisposition.FileName = "SampleImg";                
    }

    return result;
}

どのように解決するのですか?

ajaxを使用してバイナリファイルをダウンロードするためのサポートは素晴らしいではありませんが、それは非常に多くのまだ として開発中です。 .

簡単なダウンロード方法です。

これはすべてのブラウザでサポートされており、明らかに同じように WebApi リクエストをトリガーします。

$scope.downloadFile = function(downloadPath) { 
    window.open(downloadPath, '_blank', '');  
}

Ajaxによるバイナリダウンロード方式。

バイナリファイルをダウンロードするためにajaxを使用することは、いくつかのブラウザで行うことができ、以下は、Chrome、Internet Explorer、FireFoxおよびSafariの最新のフレーバーで動作する実装です。

これは arraybuffer レスポンスタイプに変換され、JavaScript の blob に変換され、保存するために saveBlob メソッドを使用して保存するように提示するか (ただし、これは現在 Internet Explorer にのみ存在します)、または Blob データ URL に変換してブラウザで開き、その MIME タイプがブラウザでの表示に対応している場合はダウンロード ダイアログを表示します。

Internet Explorer 11 のサポート (修正済み)

注意: Internet Explorer 11 は msSaveBlob 関数を使うことを嫌いました。おそらくセキュリティ機能ですが、もっと可能性が高いのは欠陥です。 var saveBlob = navigator.msSaveBlob || navigator.webkitSaveBlob ... etc. を使って、利用可能な saveBlob のサポートは例外を引き起こしたため、以下のコードでは navigator.msSaveBlob を別々にテストするようになりました。ありがとうございました。マイクロソフト

// Based on an implementation here: web.student.tuwien.ac.at/~e0427417/jsdownload.html
$scope.downloadFile = function(httpPath) {
    // Use an arraybuffer
    $http.get(httpPath, { responseType: 'arraybuffer' })
    .success( function(data, status, headers) {

        var octetStreamMime = 'application/octet-stream';
        var success = false;

        // Get the headers
        headers = headers();

        // Get the filename from the x-filename header or default to "download.bin"
        var filename = headers['x-filename'] || 'download.bin';

        // Determine the content type from the header or default to "application/octet-stream"
        var contentType = headers['content-type'] || octetStreamMime;

        try
        {
            // Try using msSaveBlob if supported
            console.log("Trying saveBlob method ...");
            var blob = new Blob([data], { type: contentType });
            if(navigator.msSaveBlob)
                navigator.msSaveBlob(blob, filename);
            else {
                // Try using other saveBlob implementations, if available
                var saveBlob = navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;
                if(saveBlob === undefined) throw "Not supported";
                saveBlob(blob, filename);
            }
            console.log("saveBlob succeeded");
            success = true;
        } catch(ex)
        {
            console.log("saveBlob method failed with the following exception:");
            console.log(ex);
        }

        if(!success)
        {
            // Get the blob url creator
            var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
            if(urlCreator)
            {
                // Try to use a download link
                var link = document.createElement('a');
                if('download' in link)
                {
                    // Try to simulate a click
                    try
                    {
                        // Prepare a blob URL
                        console.log("Trying download link method with simulated click ...");
                        var blob = new Blob([data], { type: contentType });
                        var url = urlCreator.createObjectURL(blob);
                        link.setAttribute('href', url);

                        // Set the download attribute (Supported in Chrome 14+ / Firefox 20+)
                        link.setAttribute("download", filename);

                        // Simulate clicking the download link
                        var event = document.createEvent('MouseEvents');
                        event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
                        link.dispatchEvent(event);
                        console.log("Download link method with simulated click succeeded");
                        success = true;

                    } catch(ex) {
                        console.log("Download link method with simulated click failed with the following exception:");
                        console.log(ex);
                    }
                }

                if(!success)
                {
                    // Fallback to window.location method
                    try
                    {
                        // Prepare a blob URL
                        // Use application/octet-stream when using window.location to force download
                        console.log("Trying download link method with window.location ...");
                        var blob = new Blob([data], { type: octetStreamMime });
                        var url = urlCreator.createObjectURL(blob);
                        window.location = url;
                        console.log("Download link method with window.location succeeded");
                        success = true;
                    } catch(ex) {
                        console.log("Download link method with window.location failed with the following exception:");
                        console.log(ex);
                    }
                }

            }
        }

        if(!success)
        {
            // Fallback to window.open method
            console.log("No methods worked for saving the arraybuffer, using last resort window.open");
            window.open(httpPath, '_blank', '');
        }
    })
    .error(function(data, status) {
        console.log("Request failed with status: " + status);

        // Optionally write the error out to scope
        $scope.errorDetails = "Request failed with status: " + status;
    });
};

使用方法

var downloadPath = "/files/instructions.pdf";
$scope.downloadFile(downloadPath);

注意事項

以下のヘッダを返すように、WebApiメソッドを修正する必要があります。

  • 私は x-filename ヘッダを使ってファイル名を送信しています。これは便宜上のカスタムヘッダですが、ファイル名を content-disposition ヘッダから正規表現を用いてファイル名を抽出することができます。

  • を設定する必要があります。 content-type mime ヘッダを設定する必要があります。

お役に立てれば幸いです。