WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

ダウンロードの際の拡張子

by WebSurfer 2016年6月12日 15:27

以下は Internet Exploler (IE) に限った話ですのでご注意ください。

IE でファイルをダウンロードする際、応答ヘッダに Content-Type のみが指定されていて、Content-Disposition が指定されてない場合、ファイルの拡張子はどうなるかという話を書きます。

レジストリでの拡張子設定

簡単に言うと、Microsoft の Support の記事「ファイルのダウンロードダイアログで表示されるファイル名の命名規則」の「詳細」のセクションの 2 に書いてありますように、レジストリの HKEY_CLASS_ROOT\MIME\Database\Content Type の設定によります。

具体例を書くと以下の通りです。

上の画像はレジストリの Content Type が image/tiff の拡張子の設定です。自分の開発マシン(Vista SP2 32-bit)ではデフォルトで Extension のデータは .tif になっていました。

開発マシンのローカル IIS7 に設定した images フォルダに、内容は全く同じで拡張子のみ .tiff と .tif と異なる 2 つの tiff 画像ファイルを作り、以下のように a 要素で直リンクします。それをブラウザに表示してリンクをクリックするとどうなるでしょうか?

<a href="/images/tiffdocument.tiff">tiffdocument.tiff</a>

<a href="/images/tiffdocument.tif">tiffdocument.tif</a>

実際に 2 つのファイルの拡張子は .tiff / .tif と異なるのですが、IIS7 がそれらの画像を取得してダウンロードする際、応答ヘッダに含まれる Content-Type はいずれの場合も image/tiff と設定します。(注:image/tif では IE が認識できません)

Content Type: image/tiff を受信した IE のあるクライアント PC のレジストリ設定は、上の画像が示すように image/tiff の Extension のデータが .tif となっているので、ダウンロードされた画像ファイルの名前.拡張子はどちらのリンクも tiffdocument.tif になります。

ちなみに、上の画像のレジストリの Extension のデータ .tif を .tiff に変更すると、ダウンロードされたファイルの拡張子は .tiff になります。

ダウンロードされたファイルのファイル名.拡張子を実際のファイルの通りにするには、サーバー側で Content-Disposition ヘッダでファイル名.拡張子をきちんと指定すれば、IE の場合は指定したとおりになります。

ただし、先の記事「ダウンロードの際の拡張子 と MIME Type の指定」に書きましたように、Content-Type の方を優先するブラウザもあります。

なので、ダウンロードするための HTTP ハンドラ等を作る際は、Content-Type と Content-Disposition の両方を正しく設定するように注意した方がよさそうです。

なお、プログラムで Content-Type を設定する際は image/tif ではなくて image/tiff としないと IE は認識しませんので注意してください。image/jpg も同様にダメで image/jpeg としないと IE は認識しません。

Tags: ,

Upload Download

ダウンロードの際の拡張子 と MIME Type の指定

by WebSurfer 2010年9月2日 22:42

MSDN フォーラムで、IE で xlsm をダウンロードすると zip 形式になってしまい、直接 Excel で開けないという話があったので、ちょっと調べてみました。

結局、単にそれはサーバー側の Web アプリの問題だったのですが、調査の結果、自分が知らなかったことがいろいろあったので、忘れないように書いておきます。

ブラウザは、ヘッダーの Content-Disposition: attachment; filename= で指定する拡張子と、Content-Type: で指定する MIME Type のどちらでファイルの種類を判断するでしょうか?

検証した結果は以下のとおりでした。簡単に言うと、IE8 は拡張子で判断、Opera は MIME Type で判断、Forefox は拡張子と MINE Type の指定が違う場合結果は未定義のようです。

ブラウザ Ext: xlsm
MT: xlsm
Ext: xlsm
MT: zip
Ext: zip
MT: zip
Ext: zip
MT: xlsm
IE8 Excel Excel Zip Zip
Firefox 3.6.8 Excel Zip Zip Zip
Opera 10.61 Excel Zip Zip Excel

上の表で、Ext は Content-Disposition に設定した拡張子、MT は Content-Type に設定した MIME Type です。

検証に使ったファイルは、有効な xlsm 形式のファイルで、拡張子は正しく xlsm としており、検証の間、中身も名前も一切変えていません。

クライアントの OS は Vista SP2 です。拡張子とアプリケーションの関連付けは、xlms は Excel、zip は WinZip としています。Web サーバーは Windows Server 2008 の IIS7, ASP.NET 3.5 SP1 です。

予想外の動きをしたのは Opera で、拡張子と MIME Type が異なる場合、拡張子を MIME Type に合わせて書き換えてしまいます。下の画像は、拡張子を xlsm、MIME Type を zip とした場合の例です。元のファイル名 001.xlsm が 001.zip に書き換えられています。

Opera のファイルダウンロード時のダイアログ

直リンクの場合(a 要素の href 属性にサーバーに置いた xlsm ファイルを指定した場合)、ヘッダーは以下のようになります。ブラウザは正しく判断出来るようです。

Content-Type: application/vnd.ms-excel.sheet.macroEnabled.12
Last-Modified: Thu, 02 Sep 2010 13:07:58 GMT
Accept-Ranges: bytes
ETag: "3e8647dd9f4acb1:0"
X-Powered-By: ASP.NET
Date: Thu, 02 Sep 2010 13:12:12 GMT
Content-Length: 12477

ちなみに、HTTP ハンドラーを使った場合���ヘッダーは以下のようになります。

Cache-Control: private
Content-Type: application/vnd.ms-excel.sheet.macroEnabled.12
Content-Disposition: attachment; filename=001.xlsm
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Thu, 02 Sep 2010 13:21:00 GMT
Content-Length: 12477

検証に使った HTTP ハンドラのコードを参考までにアップしておきます。

<%@ WebHandler Language="C#" Class="_045_Handler" %>

using System;
using System.Web;
using System.IO;

public class _045_Handler : IHttpHandler 
{
  public void ProcessRequest(HttpContext context)
  {
    string path = 
      context.Server.MapPath("~/Test/data/001.xlsm");

    if (!File.Exists(path))
    {
      return;
    }
        
    string type = context.Request.QueryString["type"];

    switch (type)
    {
      case "xlsm_xlsm":
        SetHeader(context, "001.xlsm", 
          "application/vnd.ms-excel.sheet.macroEnabled.12");
        break;
      case "xlsm_zip":
        SetHeader(context, "001.xlsm", 
          "application/x-zip-compressed");
        break;
      case "zip_zip":
        SetHeader(context, "001.zip", 
          "application/x-zip-compressed");
        break;
      case "zip_xlsm":
        SetHeader(context, "001.zip", 
          "application/vnd.ms-excel.sheet.macroEnabled.12");
        break;
      default:
        SetHeader(context, "001.xlsm", 
          "application/vnd.ms-excel.sheet.macroEnabled.12");
        break;                
    }
    context.Response.TransmitFile(path);
    context.Response.End();
  }
    
  public bool IsReusable
  {
    get {
      return false;
    }
  }

  protected void SetHeader(HttpContext context, string name, string type)
  {
    context.Response.AppendHeader("Content-Disposition",
      "attachment; filename=" + name);
    context.Response.ContentType = type;
  }
}

他に、今回知った新(?)事実は、Excel 2007 からファイル形式が変わったということです。何をいまさらと言われるかも知れませんが。(汗)

Excel 2007 からはファイルはバイナリではなくなり、xml 形式のテキストを zip で圧縮したものになっているそうです。確かに WinZip で xlsm ファイルを開くことができ、中身は xml 形式のテキストファイルでした。

また、xlsm は「マクロ有効ブック」というそうで、セキュリティ対策として、拡張子からマクロが含まれていることが分かるような名前の規則を作ったそうです。

------------ 2011/5/21 追記 ------------

IE8 は拡張子で判断と書きましたが、やはり IE はそのような仕様になっているようです。以下のページを参考にしてください。

ファイルのダウンロードダイアログで表示されるファイル名の命名規則

即ち、上のページの「詳細」の 1 番目に書いてあるとおり「Content-Disposition: ヘッダが存在する場合は、filename パラメータで設定されたファイル名が利用されます。」ということです。

サポートページには書いてないですが、Content-Disposition: ヘッダでファイル名が指定してあれば、Content-Type: の指定は無視されます。

2 番目の「HTTP レスポンス内に存在する、送られてきた Content-Type が、レジストリの HKEY_CLASS_ROOT\MIME\Database\Content Type 以下に存在するかどうか・・・」というのは、Content-Disposition: ヘッダの filename パラメータにファイル名の指定がない場合に限るようです。

Tags: ,

Upload Download

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar