none
Windows10のIE11で、POSTメソッドでのファイルダウンロードができない。 RRS feed

  • 質問

  • 現在、Windows10のIE11では、ファイル(Excel、PDF、画像等)を出力するcgiをPOSTメソッドで呼び出すと、そのファイルを取得することができないようです。

    http://hoikunet.jp/test/test.html  にサンプルを作りました。
    [PDF表示]のボタンが2つありますが、PDFファイルを出力するcgiを、上のボタンはGETメソッドで、下のボタンはPOSTメソッドで呼び出します。

    cgiの中身は、

    #!/usr/bin/perl
    use strict;
    use CGI;
    sub main {
     my $cgi = new CGI;
     my $pdffile = '/[ディレクトリ名]/t.pdf';
     print $cgi->header(-type=>'application/pdf');
     my $size = -s $pdffile;
     my $buf;
     open(IN, $pdffile);
     binmode(IN);
     binmode(STDOUT);
     read(IN, $buf, $size);
     print $buf;
     close(IN);
     return(1);
    }
    main();
    exit(0);

    で、PDFファイルを読み込んでそのまま書き出しているだけです。
     (もちろん、実際に使用したいスクリプトはパラメータに応じてPDFファイルを生成するものですが、単純化しました。)

    Windows7、8.1のIE11ではどちらのボタンをクリックしてもPDFファイルが表示されます。
    Windows10のIE11では上のボタンは問題ありませんが、下のボタンは何も表示されないか、または「Web ページの有効期限が切れています」が表示されて、ファイルを取得することができません。

    PDF以外のファイルでも、同様の現象がおきます。
    ・Excelファイル    print $cgi->header(-type=>'application/vnd.ms-excel');
    ・Jpegファイル    print $cgi->header(-type=>'image/jpeg');

    どうやら、Content-Type: text/html 以外は POSTメソッドが使えないようです。

    Windows10のIE11の不具合のように思いますが、解決策はあるのでしょうか。

    2015年10月20日 8:50

回答

  • 手元(IE11 on Win10)で同様の perl を書き写した後、明示的に ISO-8859-1 を指定すると、確かに開発者ツールでも(保留中)表示でとどまりますので、それが原因とみていいと思いますよ。

    (該当の CGI はすでに変わっているのか、ブラウザ側の設定によって ISO-8859-1 がつく or つかないのかは外部から検証しようがありません。
    よって、私は純粋に「ISO-8859-1 がつくと問題が起きるかどうか」を手元で検証。なお、IE11 on Win8.1 Update では発生せず)

    以下は自分の Web スペースを用いた実験において、同じ CGI で charset の指定を utf-8 と ISO-8859-1 で切り分けたのみ。
    ISO-8859-1 ではダウンロードが始まらず、「保留中」表示となりました。
    ISO-8859-1 版の CGI に IE11 on Win8.1 Update からアクセスすればきちんとダウンロードされるので、ブラウザーの解釈の差であろうと思います。

    ※なお、質問者が示した URL の CGI で ISO-8859-1 つきで出力されうること、そのときに失敗することは Hebikuzure さんがすでに検証され、そのときのパケットキャプチャの画像も添付されています。お見逃しなきよう。

    • 編集済み AzuleanMVP 2015年10月22日 17:10
    • 回答としてマーク kishosha 2015年10月23日 13:34
    2015年10月22日 14:52
  • 皆様、ご迷惑をおかけしました。

    色々な条件で試してみた結果、
    Windows10+IE11 でPOSTメソッドのPDF表示がうまくいかなかった原因は、
    Content-Disposition:  attachment; filename="xxx.pdf"
    ではありませんでした。

    perl の問題ですが、CGI.pm のheader出力機能でcharsetを指定しないと、HTMLヘッダに
        charset=ISO-8859-1
    と出力してしまうのが原因でした。

     print $cgi->header(-type=>'application/pdf',-charset=>'utf-8');

    とすれば、問題ありません。

    なお、Content-Disposition:  attachment; filename="xxx.pdf"
              (CGI.pmのheader出力では、-attachment=>'xxx.pdf'   )
    を指定しないでPDFファイルを出力すると、
    ブラウザ内に表示されます。

    以上、ご報告いたします。

    • 回答としてマーク 星 睦美 2015年10月22日 6:22
    2015年10月22日 5:06
  • ブラウザ内に表示されます。
    私はAdobe Readerをインストールしていないのでブラウザー内に表示されることはありません。ダウンロードされた後、Edgeが起動していました。私の環境では動作していた理由はこれですかねぇ…?
    • 回答としてマーク kishosha 2015年10月23日 14:01
    2015年10月22日 5:15
  • 質問者さんの作られたサンプルは随時更新されています。charset=ISO-8859-1を含んでいないタイミングでアクセスされただけでは?

    PerlのCGIモジュールはレスポンスヘッダーにContent-Lengthが含まれていなかった場合、自動的にchunkedエンコーディングで応答します。

    • 回答としてマーク kishosha 2015年10月23日 13:35
    2015年10月23日 0:38
  • 私が最初に投稿したときのスクリプトは、その後に検証中に変えてしまっていました。

    このために混乱を起こして申し訳ございません。

    あらためて、

    http://hoikunet.jp/test/test.html

    に、

    (1) print $cgi->header(-type=>'application/pdf');  (charset=ISO-8859-1が付くケース)

    (2) print $cgi->header(-type=>'application/pdf',-charset=>'utf-8');

    の両方を GET / POST で呼び出せるようにしました。

    UserAgentによって処理は変えていません。

    Acrobat Reader がインストールされていれば、Win7/8.1 のIE11では、全てブラウザ内に表示されますが、

    Win10 のIE11では (1)の POST だけ NG となります。

    • 回答としてマーク kishosha 2015年10月23日 13:36
    2015年10月23日 13:33
  • 回答およびサンプルの書き直しをありがとうございました。

    結局 charset=ISO-8859-1 の有無だけが問題で、2015年10月21日 9:06 のレスで (3) が OK だったのは Content-Disposition の有無は関係なく、以下のようになっていたからで、

    Content-type:application/pdf;
    Content-Disposition:attachment;filename=t.pdf

    以下のように charset=ISO-8859-1 があるケースではやはりダメだったということですよね?

    Content-Type: application/pdf; charset=ISO-8859-1
    Content-Disposition:attachment;filename=t.pdf

    理解が間違っていたらご指摘ください。





    • 編集済み SurferOnWww 2015年10月23日 14:24 Content-Disposition
    • 回答としてマーク kishosha 2015年10月23日 15:10
    2015年10月23日 14:10
  • はい、その通りです。

    charset=ISO-8859-1 は意図して付けたのではなく、perl のCGI.pmモジュールが付けていたため、 2015年10月21日 9:06 の時点ではそれが分かっていなかった、ということで、実際はご指摘いただいた通りです。

    • 回答としてマーク kishosha 2015年10月23日 15:14
    2015年10月23日 15:09

すべての返信

  • 手元のWindows 10 IE11では普通にダウンロードされました。何か別のところに原因があるのかもしれません。
    2015年10月20日 10:57
  • こんにちは。

    何が原因かはわからないですが、私の環境では発生しました。

    • Windows10 Pro 64bit
    • Internet Explorer 11.0.10240
    2015年10月20日 14:24
    モデレータ
  • 再現するのでパケット キャプチャしてみました。

    Windows 10 環境で、上が IE11 の場合、下が Edge の場合です。最初のリクエストが上のボタン、次のリクエストが下のボタンです。そもそも Edge ではエンティティの無い POST を GET に変換してリクエストしているみたいですね。しかもボタンクリック 1回につき 2回ずつリクエストしているし。どうしてそうなるのかちょっと情報がない動作ですね。また IE11 で POST した場合もレスポンスとしてすべてのエンティティがちゃんと返却されています。

    どうも IE / Edge それぞれの内部動作に絡みそうなので、ここで情報が出てこなければ、

    1. US の Stack Overflow に internet-explorer タグを付けて投稿する (これが現在の IE-Dev の正式サポート フォーラム)
    2. 有償サポートを利用する

    という順でしょう (すぐに有償サポートでもよいですが)。


    hebikuzure



    2015年10月20日 15:53
    モデレータ
  • 試してみてもよさそうなのは

    • クライアント側で、POST する時に (ダミーでよいので) フォーム データが送信さるれるようにする
    • サーバー側で、content-disposition を指定する (attachment でファイル名も指定するなど)

    でしょうか。これで変化があればヒントになると思います。


    hebikuzure








    2015年10月21日 6:45
    モデレータ
  • 佐祐理さん、Tak1waさん、Hebikuzureさん、返信頂きありがとうございます。

    Hebikuzureさんのアドバイスに従って色々と試したところ、解決策を見出すことができました。

    (1) まず、cgiの呼出元のformにダミーのデータを追加しました。
         <input type="hidden" name="d" value="dummy">

        → 結果は変わらず。
        (ちなみに、Hebikuzureさんが書かれている通り、Edgeでこのケースでは POST のまま送信されました。)


    (2) 次に CGI.pm のheader出力に attachment を追加しました。
          print $cgi->header(-type=>'application/pdf',-attachment=>'test.pdf');

        → 結果は変わらず。
     
    (3) 最後に、CGI.pm のheader出力機能は使わずに、直接HTTPへッダを書くようにしました。
     print "Content-type: application/pdf;\n";
     print "Content-Disposition:   attachment; filename=\"test.pdf\"\n";
     print "\n";

        → POSTでもPDFファイルがダウンロードできるようになりました。

    Excelファイルのダウンロードでも同様の結果となりました。

    結論としては、Windows10のIE11で POSTメソッドを使ってファイルダウンロードする場合は、
    ベッダに Content-Disposition:   attachment; filename="..." を出力する必要がある、ということです。

    ありがとうございました。

    追記) 本投稿で、なぜか Content-Dis   以下が消えてしまうので、余分な空白を入れて表示されるようにしました。このページのバグ?





    • 編集済み kishosha 2015年10月21日 9:06
    2015年10月21日 8:49
  • POST で返却されるコンテンツのファイル名が、IE11 の場合 POST 先の t.cgi と認識されて、PDF として扱うのに失敗してしまうのかもしれません。ファイル名正しく拡張子 .pdf を指定することで回避できるのでしよう。


    hebikuzure

    2015年10月21日 8:59
    モデレータ
  • ところでなんで私の環境では動作していたんだろう…?

    とりあえずダウンロードを期待していて、WebサーバーからContent-Dispositionなどのヘッダーを返すのであれば、呼び出すHTML側も target="_blank" は不要かと思います。今、サンプルを実行してみたところ、新たな空白タブが表示されるものの、元のページに対してダウンロードダイアログ(? ウィンドウ下部のやつ)が表示されていました。

    2015年10月21日 9:10
  • 今回の話は IE の問題ということではなく、Web アプリ側でやるべきことをちゃんとやってなかったために起きた問題ということではないのでしょうか?

    ブラウザによってファイルの種類を判断する方法が異なるということもあります。昔の検証結果ですが以下の記事のようになりました。

    ダウンロードの際の拡張子 と MIME Type の指定
    http://surferonwww.info/BlogEngine/post/2010/09/02/Downloading-file-by-setting-extension-and-mime-type-in-header.aspx

    簡単に言うと、IE は、Content-Disposition; ヘッダが存在する場合は filename パラメータで設定されたファイル名の拡張子を優先的に使い、Content-Type: ヘッダの指定は無視される。逆に、Opera など、Content-Type: ヘッダの指定を優先的に使うものもあるという結果でした。

    なので、Content-Disposition; ヘッダと Content-Type: ヘッダの両方を正しく指定しておくべきだと思います。それをしないで何かおかしいというのは、ちょっと違うのではないかと・・・



    • 編集済み SurferOnWww 2015年10月21日 10:18 Content-Disposition;
    2015年10月21日 10:03
  • イントラネットのアプリケーションなど動作環境が限定されるのであれば「不備」とまで言い切れるかどうかはともかく、POST でダウンロードさせる場合、そのファイル名の決まり方とその取扱い方法はブラウザーの実装や設定 (MIME スニッフィングの有効無効、PDF を開くアプリの設定など) によって変わったりするので、content-disposition でファイル名を指定しておいたほうが無難であることは間違いないですね。


    hebikuzure

    2015年10月21日 16:59
    モデレータ
  • 皆様、ご迷惑をおかけしました。

    色々な条件で試してみた結果、
    Windows10+IE11 でPOSTメソッドのPDF表示がうまくいかなかった原因は、
    Content-Disposition:  attachment; filename="xxx.pdf"
    ではありませんでした。

    perl の問題ですが、CGI.pm のheader出力機能でcharsetを指定しないと、HTMLヘッダに
        charset=ISO-8859-1
    と出力してしまうのが原因でした。

     print $cgi->header(-type=>'application/pdf',-charset=>'utf-8');

    とすれば、問題ありません。

    なお、Content-Disposition:  attachment; filename="xxx.pdf"
              (CGI.pmのheader出力では、-attachment=>'xxx.pdf'   )
    を指定しないでPDFファイルを出力すると、
    ブラウザ内に表示されます。

    以上、ご報告いたします。

    • 回答としてマーク 星 睦美 2015年10月22日 6:22
    2015年10月22日 5:06
  • ブラウザ内に表示されます。
    私はAdobe Readerをインストールしていないのでブラウザー内に表示されることはありません。ダウンロードされた後、Edgeが起動していました。私の環境では動作していた理由はこれですかねぇ…?
    • 回答としてマーク kishosha 2015年10月23日 14:01
    2015年10月22日 5:15
  • ウチの環境 (現象再現) でも Adobe Reader はインストールしておらず、PDF は Edge で開くようになっているのですがねえ。さらに別の要因があるみたいです (もはや本題からは外れますが)。


    hebikuzure

    2015年10月22日 6:50
    モデレータ
  • > perl の問題ですが、CGI.pm のheader出力機能でcharsetを指定しないと、HTMLヘッダに
    >     charset=ISO-8859-1
    > と出力してしまうのが原因でした。

    IE9 でですが、一番最初の質問で書かれた「サンプル」ページからダウンロードしてみましたが、Content-Type は以下の通りでどこにも charset=ISO-8859-1 というのはありませんけど?(そもそも charset=ISO-8859-1 が原因と言うのも訳がわかりませんけど)

    要求ヘッダの User-Agent を見て応答を変えてるということはないですよね? あと、chunked コーディングもちょっと気になるのですが意図的でしょうか?

    あともう一つ、「ファイルダウンロードができない」というのは確かなんでしょうか? ダウンロードができないわけではなくて、ダウンロードはできているが Adobe Reader がブラウザのプラグインにならないとかの理由で単に表示されないだけと言うことはないのですか?
    • 編集済み SurferOnWww 2015年10月22日 9:06 誤字訂正+追記
    2015年10月22日 7:18
  • 星 睦美さん>

    質問者さんのレスに「回答としてマーク」を付けられてますが、そこに書いてあった、

    > HTMLヘッダに
    >     charset=ISO-8859-1
    > と出力してしまうのが原因でした。

    ということで間違いないのでしょうか?

    charset=ISO-8859-1 があると何故ダメなのか、理由をご存知でしたらお聞かせいただけませんか?

    2015年10月22日 9:12
  • 手元(IE11 on Win10)で同様の perl を書き写した後、明示的に ISO-8859-1 を指定すると、確かに開発者ツールでも(保留中)表示でとどまりますので、それが原因とみていいと思いますよ。

    (該当の CGI はすでに変わっているのか、ブラウザ側の設定によって ISO-8859-1 がつく or つかないのかは外部から検証しようがありません。
    よって、私は純粋に「ISO-8859-1 がつくと問題が起きるかどうか」を手元で検証。なお、IE11 on Win8.1 Update では発生せず)

    以下は自分の Web スペースを用いた実験において、同じ CGI で charset の指定を utf-8 と ISO-8859-1 で切り分けたのみ。
    ISO-8859-1 ではダウンロードが始まらず、「保留中」表示となりました。
    ISO-8859-1 版の CGI に IE11 on Win8.1 Update からアクセスすればきちんとダウンロードされるので、ブラウザーの解釈の差であろうと思います。

    ※なお、質問者が示した URL の CGI で ISO-8859-1 つきで出力されうること、そのときに失敗することは Hebikuzure さんがすでに検証され、そのときのパケットキャプチャの画像も添付されています。お見逃しなきよう。

    • 編集済み AzuleanMVP 2015年10月22日 17:10
    • 回答としてマーク kishosha 2015年10月23日 13:34
    2015年10月22日 14:52
  • ISO-8859-1が原因ということで気付いたのですが、私が検証したWindows 10は2台とも英語版でした。バグ報告の際には「英語版以外の環境(少なくとも日本語版)で発生する」と添えないと再現せずと突き返されそうです。
    2015年10月22日 20:57
  • フォーラム オペレーターの星 睦美です。kishosha さん、こんにちは。

    解決した内容をお知らせいただきありがとうございます。私のほうでkishosha さんの返信に[回答としてマーク] させていただきましたが、今回参考になったユーザーからの返信にはkishosha さんから[回答としてマーク] いただければ幸いです。

    今後ともInternet Explorer フォーラムをお役立てください。


    フォーラム オペレーター 星 睦美 - MSDN Community Support

    2015年10月23日 0:15
  • Azulean さん>

    検証結果の連絡をありがとうござました。

    だた、最後のところ、

    > お見逃しなきよう。

    私へのレスだと思いますが、そうだとすると話が噛み合ってないです。

    見逃していようがいまいが、先の私のレスの疑問(要点下記)は解消しないですから。質問者さんの回答に期待したいと思います。

    (1) IE9 では charset=ISO-8859-1 は含まれない。ブラウザによって応答を変えている?

    (2) chunked が気になるが意図的?

    (3) ダウンロード(クライアント PC は受け取っているという意味で)はできていて、その後の問題ではないか?

    正直パケットキャプチャ画像に charset=ISO-8859-1 があるのは見てなかったですけどね。でも上記の話には関係ないと思いますけど。(キャプチャ画像では 2231 bytes 受信したように見えるので、見ていれば (3) についてはその想像を裏付ける一つだったと言えるかもしれませんが)

    #自分で検証すればいいと思われるかもしれませんが、Windows 10 + IE11 は持っていないので・・・


    • 編集済み SurferOnWww 2015年10月23日 0:21 タイポ訂正
    2015年10月23日 0:17
  • 質問者さんの作られたサンプルは随時更新されています。charset=ISO-8859-1を含んでいないタイミングでアクセスされただけでは?

    PerlのCGIモジュールはレスポンスヘッダーにContent-Lengthが含まれていなかった場合、自動的にchunkedエンコーディングで応答します。

    • 回答としてマーク kishosha 2015年10月23日 13:35
    2015年10月23日 0:38
  • どの投稿への返信にするか迷うところですが、一応最新の書き込みに返信の形で。

    スクリーンショットを載せた時のパケット データは捨てちゃったのですが、その際に確認した限りでは、現象が発生する場合でもネットワーク レベル (HTTP プロトコル レベル) では PDF ファイルは全部正しくレスポンスされていました。

    それを受け取った WinInet より上のレイヤーで、正しく (と言うか、期待通りに) 表示させることができないようです。


    hebikuzure

    2015年10月23日 8:09
    モデレータ
  • 私が最初に投稿したときのスクリプトは、その後に検証中に変えてしまっていました。

    このために混乱を起こして申し訳ございません。

    あらためて、

    http://hoikunet.jp/test/test.html

    に、

    (1) print $cgi->header(-type=>'application/pdf');  (charset=ISO-8859-1が付くケース)

    (2) print $cgi->header(-type=>'application/pdf',-charset=>'utf-8');

    の両方を GET / POST で呼び出せるようにしました。

    UserAgentによって処理は変えていません。

    Acrobat Reader がインストールされていれば、Win7/8.1 のIE11では、全てブラウザ内に表示されますが、

    Win10 のIE11では (1)の POST だけ NG となります。

    • 回答としてマーク kishosha 2015年10月23日 13:36
    2015年10月23日 13:33
  • 回答およびサンプルの書き直しをありがとうございました。

    結局 charset=ISO-8859-1 の有無だけが問題で、2015年10月21日 9:06 のレスで (3) が OK だったのは Content-Disposition の有無は関係なく、以下のようになっていたからで、

    Content-type:application/pdf;
    Content-Disposition:attachment;filename=t.pdf

    以下のように charset=ISO-8859-1 があるケースではやはりダメだったということですよね?

    Content-Type: application/pdf; charset=ISO-8859-1
    Content-Disposition:attachment;filename=t.pdf

    理解が間違っていたらご指摘ください。





    • 編集済み SurferOnWww 2015年10月23日 14:24 Content-Disposition
    • 回答としてマーク kishosha 2015年10月23日 15:10
    2015年10月23日 14:10
  • はい、その通りです。

    charset=ISO-8859-1 は意図して付けたのではなく、perl のCGI.pmモジュールが付けていたため、 2015年10月21日 9:06 の時点ではそれが分かっていなかった、ということで、実際はご指摘いただいた通りです。

    • 回答としてマーク kishosha 2015年10月23日 15:14
    2015年10月23日 15:09