読者です 読者をやめる 読者になる 読者になる

れみゅーぶろぐ

某(元)高専生が多彩なジャンルにわたって書くブログ。非常に真面目なブログであると自負しております(要出典)。Twitter:@_remew_

Flaskとnginxで作ったファイルアップローダーのバグ(?)を直した(?)おはなし

ぼく「ファイルアップローダー作った(^O^)」

後輩「これ便利ですね」

ぼく「(感涙に咽びなく)」

 

( ^o^)<無事にファイルアップローダー完成したぞ。嬉しいぞ。

( ˘⊖˘) 。o(まてよ、このファイルアップローダーにhtmlファイルを投げたらどうなるんだ?)

|| ┗(☋` )┓三ためしてみよう

( ◠‿◠ )☛htmlがちゃんとページとして表示されるぞ

▂▅▇█▓▒░(’ω’)░▒▓█▇▅▂うわあああああああ

 

ぼく「これ悪意のあるページとかアップロードされてなんやかんやされたらまずそう?(直感)」

後輩「すぐ直したほうが良さそう」

 

そして我々調査隊はHTMLがページとして表示されないようにするためにジャングルの奥地へと・・・

 

さてどうしよう。wavとかmp3とかが再生されて、pngとかjpegが表示されるのはいいんだけど、HTMLが表示されるのは困るなぁ・・・

よし、ダウンロードさせよう!

たぶんFlaskのAPIさがしたらあるでしょ(希望的観測)

お、今使ってるメソッド(send_from_directory)に引数追加すればよさそう!

 

旧:send_from_directory(HOGE, huga)

新:send_from_directory(HOGE, huga, as_attachment=True)

 

これをすることによって、なんとmp3やpngなど全てのファイルの種類がダウンロードされるようになりました!!!

・・・HTMLファイルを除いては

 

は?キレそう

HTMLは未だに表示される。どうしよう。

 

待って、そもそもファイルがダウンロードされるかどうかってどういう情報で判断してるんだろう。

もしかしてヘッダに何か書かれてるのかな→その通りでした

 

Content-Disposition: attachment; filename="hoge.png" という値(?)をヘッダに追加したらダウンロードされるっぽい。

 

そしてさっきのsend_from_directoryの引数のやつはどうやら上の値をヘッダに追加するフラグだったらしい?

 

ん~~~?何故HTMLはダウンロードされないんだ~~~?

 

ここで唐突にcygwinを起動したれみゅー氏。

curl --head TARGET_URL 

 これでヘッダ見れるっぽいし見てみた。

Content-Disposition: attachment; filename="hoge.html"

追加されてませんでした。

 

気になったことがあったので、ローカルでも似たようなプログラムを書いて実行してみました。

curlすると、 

Content-Disposition: attachment; filename="hoge.html"

見事に追加されてました。

 

あれこれもしかしてnginxの設定がまずいのでは?

ということで調べて、

proxy_pass_header Content-Disposition;

とか追加しました。

これでいけるやろwとか思いながらnginxを再起動→ダウンロードされない💢💢

 

なんでだ💢💢

・・・ん???

Content-Dispositionのちょっと上に気になる文字が・・・

 

Content-type: text/html

 

ん??????

もしかしてこれが?原因?

 

そこから先は早かった・・・

 

  1. ファイルがHTMLかどうかを調べます。拡張子で。
  2. HTMLなら、ファイルを開いて中身を全部読み込みます。
  3. make_response()でレスポンスを生成します。
  4. 読み込んだ中身をレスポンスにセットします。
  5. レスポンスヘッダーのContent-Dispositionにattachment; filename=hogeを設定します。
  6. レスポンスヘッダのcontent-typeをtext/planeにします。
  7. レスポンスを返します。

これで、ねんがんのHTMLダウンロードがかなった。

HTMLじゃなかった場合は多分ブラウザで開きます。物によってはダウンロードされるけど。

 

わーいわーい

てかめっちゃ長い文章書いた。久しぶり。

 

2015/05/01 17:20 追記&ちょっと内容変更

参考にしたサイトとか。

Flaskをさわってみる - るびゅ備忘録

Content disposition header on Nginx - Server Fault

http headers - nginx pass filetype to backend server - Stack Overflow