[解決済み] AngularJSを使ったASP.NET Web APIメソッドからのファイルダウンロード
質問
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 ヘッダを設定する必要があります。
お役に立てれば幸いです。
関連
-
[解決済み】取り消せないメンバはメソッドのように使えない?
-
[解決済み】ファイルやアセンブリ、またはその依存関係の1つをロードできませんでした。
-
[解決済み] jQueryを使ってドロップダウンリスト(セレクトボックス)から選択されたテキストを取得する
-
[解決済み] AngularJSを使用して、ブラウザのコンソールで$scope変数にアクセスするにはどうすればよいですか?
-
[解決済み] Chromeを使用してASP.NET Web APIがXMLの代わりにJSONを返すようにするにはどうすればよいですか?
-
[解決済み] C#で同期メソッドから非同期メソッドを呼び出すには?
-
[解決済み] AngularJSのコントローラからビューにHTMLを挿入する
-
[解決済み] ASP.NET Web APIに整数の配列を渡しますか?
-
[解決済み] ASP.NET Web APIでエラーを返すためのベストプラクティス
-
[解決済み】ASP.NET Web APIでコントローラからバイナリファイルを返す。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】文字列が有効な DateTime " format dd/MM/yyyy " として認識されなかった。
-
[解決済み】統合マネージドパイプラインモードで適用されないASP.NETの設定が検出された
-
[解決済み】ソケットのアドレス(プロトコル/ネットワークアドレス/ポート)は、通常1つしか使用できない?
-
[解決済み】プロジェクトビルド時のエラー。エディタでスクリプトにコンパイルエラーがあるため、Playerのビルドにエラーが発生する
-
[解決済み】「入力文字列が正しい形式ではありませんでした」エラーの解決方法は?[重複しています]。
-
[解決済み】リソースの読み込みに失敗した:ステータス500(内部サーバーエラー)のサーバーの応答)
-
[解決済み] [Solved] アセンブリ System.Web.Extensions dll はどこにありますか?
-
[解決済み】2つ(またはそれ以上)のリストを1つに統合する(C# .NETで
-
[解決済み】インデックスが範囲外でした。コレクションパラメータname:indexのサイズより小さく、非負でなければなりません。
-
[解決済み] デバイスがiOSであるかどうかを検出する