TypeScript で fetch と XMLHttpRequest の非同期処理を実装してみる

Web アプリケーションのファイル(画像・動画・テキスト・CSV)ダウンロードは今更感がありますが、比較的新しい言語の ASP.NET Core で紹介したいと思います。せっかくなので View は jQuery ではなく、TypeScript で実装してみます。

と、その前に。ダウンロードに限ったことではないですが、Web において重要な MIME(マイム)について軽く触れます。

MIMEとは

MIME(マイム)は文書、ファイル、またはバイト列の性質や形式を示す規格です。RFC 6838で定義されています。

では、どんな定義かいくつか見てみます。

代表例
  • text/css
  • text/javascript
  • application/octet-stream
  • text/plain

“text/css” や “text/javascript” は Web 開発の経験ある方にはお馴染みです。形式としては、タイプ/サブタイプタイプ/サブタイプ;引数=値になります。

MIMEは何のためにあるの?

重要:ブラウザーは URL を処理する方法を決定するために、ファイル拡張子ではなく MIME タイプを使用しますので、ウェブサーバーは正しい MIME タイプをレスポンスの Content-Type ヘッダーで送信することが重要です。これが正しく構成されていないと、ブラウザーはファイルの中身を誤って解釈し、サイトが正しく動作しなかったり、ダウンロードファイルが誤って扱われたりすることがあります。

MDN – Mozilla 引用:MIME

簡単に言うと、Web サーバがブラウザに、このファイルは「画像だよ」「動画だよ」「CSVだよ」って教えます。では、ASP.NET Core MVC でささっと実装して Chrome で確認してみましょう。

image/jpg 表示

ASP.NET Core MVC プロジェクトに ControllerView を作成して、まずは素直に画像を表示します。

コード

Controller

View

実装ができたので、View を表示して ImageDownloadController.GetImage の Responseヘッダーを見てみます。

Responseヘッダー

Responseヘッダーは Chrome のデベロッパーツールで確認します。

Response Headers を見ると content-type: image/png となっています。ImageDownloadController.GetImage で指定した contentType の MIMEタイプ と同じですね。

image/jpg ダウンロード

続いて、先ほど作成した Controller に画像をダウンロードするアクションメソッド、View にダウンロードボタンを実装します。

コード

Controller

View

※Firefox は、click イベントを発火する前に body などに追加しないと正常に動作しません。

Responseヘッダー

Chrome だとネットワークにリクエストが表示されなかったので Firefox のデベロッパーツールで確認します。

Response Headers に content-type: application/octet-streamcontent-disposition という項目があります。

application/octet-stream

これは、バイナリファイルでは既定です。これは未知のバイナリ形式のファイルを表すものであり、ブラウザーはふつう実行したり、実行するべきか確認したりしません。これらは Content-Disposition ヘッダーの値に attachment が設定されたかのように扱い、「名前を付けて保存」ダイアログを提案します。

MDN – Mozilla 引用:application/octet-stream

つまりブラウザは表示しようとせず、ダウンロードする MIME タイプです。

Content-Disposition

通常の HTTP レスポンスにおける Content-Disposition レスポンスヘッダーは、コンテンツがブラウザでインラインで表示されることを求められているか、つまり、Webページとして表示するか、Webページの一部として表示するか、ダウンロードしてローカルに保存する添付ファイルとするかを示します。

MDN – Mozilla 引用:Content-Disposition

attachment はダウンロードすべきであることを示し、ブラウザは filename パラメータの値を初期値として「名前を付けて保存」ダイアログを表示します。

Fetch, XMLHttpRequestでダウンロード

$.ajax() はバイナリをテキスト扱いしてしまうため Fetch、 XMLHttpRequest で実装します。

因みに $.ajax() で指定できる dataType は、”text”, “html”, “xml”, “script”, “json”, “jsonp” となります。

コード

TypeScript

View

 

まとめ

ASP.NET CoreTypeScript を使ってファイルのダウンロードを簡単に実装しました。通常の ajax を使うと text でかえってくるところとか忘れているとあれ?!となるので覚えておくといいかもしれません。他にも覚えておいた方が良いことは、download 属性同一オリジンの URL に限り動作するということです。これを忘れていると指定したファイル名とダウンロードしたファイル名が違う?!と少しはまってしまうかもしれません。

↓ 簡単な web アプリを作りながら TypeScript Modules を理解できるようにしています。
↓ もうレガシーブラウザに振り回されないアプリを作成できます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA