大規模ファイルアップロード時のブラウザ対応状況私的まとめ

送信先は、apache 2.2.3 / mod_uploader 3.1.0。 クライアント環境は WinXP x64 SP2。

各ファイル送信時、ブラウザがどんなヘッダーをPOSTしてるのか調査しました。主に Content-Length の調査。正しいファイルサイズ(正確には、正しいリクエストボディサイズ)が送信できているかを確認。

ブラウザ 2GB超 4GB超
IE6 (32bit) ×Content-Length がマイナスになる ×Content-Length が小さくなる。実際のファイルサイズの下位32bitっぽい値になる
IE6 (64bit) ×Content-Length がマイナスになる ×Content-Length が小さくなる。実際のファイルサイズの下位32bitっぽい値になる
Firefox 14.0.1 ×Content-Length がマイナスになる ×Content-Length が極端に小さくなる(?)
Opera 12.0 ○アップロード可能。Content-Length正常値 ×ファイルの中身が空(0Byte)の multipart/form-data のデータが送信される様子
Chrome 20.0 ○アップロード可能。Content-Length正常値 ○アップロード可能。Content-Length正常値

2GB超/4GB超の大規模ファイルをアップロードしたい際は Chrome が安定かも。 Opera も 2GB超えを扱えますが、送信ボタン押した際に30秒ぐらい固まります。

なお、以下(私が把握出来ている)注意点

  • サーバー側も正しく Content-Length を解釈できないとアカンでー。 apache 2.2 から 4GB だか 2GB だか以上のファイルを扱えるようになったらしいので、apache 2.0 とかだと無理かも。(ココの「大ファイルサポート」に該当? 64bit なら apache 2.0 でもOKなんかな…詳細は不明。)
  • スクリプト言語系でアップロード処理する場合、すごいパフォーマンスが悪化するかも。php とか → 一旦メモリに 2GB のファイルをおいてから処理開始ー って処理だと、相当メモリ積んでないと鯖が swap しまくりに。
    • 鯖アプリが 32bit プロセスだとメモリ確保に失敗してヤバイ事になりそう。
  • つまるところ、不特定多数を相手にする場合、DoS攻撃(というか自爆)が容易に出来ちゃう環境になるのでヤバイ。皆が一斉にアップロードしはじめると容易に落ちそう。
  • ってか、GB単位を http で upload とかバカじゃねーの!

以下ブラウザが送信したヘッダー情報

IE6 (32bit) - 2.82GB 送信時

POST http://example.jp/uploader/upload//3000737340 HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*
Referer: http://example.jp/uploader/
Accept-Language: ja
Content-Type: multipart/form-data; boundary=---------------------------7dc2020206ae
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; WOW64; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)
Host: example.jp
Content-Length: -126138086
Proxy-Connection: Keep-Alive
Pragma: no-cache
Cookie: __utma=228853188.850377578.1316378493.1316378493.1316378493.1

負の値

IE6 (32bit) - 4.3GB 送信時

POST http://example.jp/uploader/upload//2195712367 HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*s
Referer: http://example.jp/uploader/
Accept-Language: ja
Content-Type: multipart/form-data; boundary=---------------------------7dc222c10542
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; WOW64; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)
Host: example.jp
Content-Length: 338387945
Connection: Keep-Alive
Pragma: no-cache
Cookie: __utma=228853188.850377578.1316378493.1316378493.1316378493.1

322.71MB になってる

IE6 (64bit) - 2.82GB 送信時

POST http://example.jp/uploader/upload//2370704091 HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, */*
Referer: http://example.jp/uploader/
Accept-Language: ja
Content-Type: multipart/form-data; boundary=---------------------------7dc37b6205ec
UA-CPU: AMD64
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Win64; x64; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)
Host: example.jp
Content-Length: -126138086
Proxy-Connection: Keep-Alive
Pragma: no-cache
Cookie: __utma=228853188.850377578.1316378493.1316378493.1316378493.1

負の値

IE6 (64bit) - 4.3GB 送信時

POST http://example.jp/uploader/upload//4083968936 HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, */*
Referer: http://example.jp/uploader/
Accept-Language: ja
Content-Type: multipart/form-data; boundary=---------------------------7dc3b92920544
UA-CPU: AMD64
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Win64; x64; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)
Host: example.jp
Content-Length: 338387952
Connection: Keep-Alive
Pragma: no-cache
Cookie: __utma=228853188.850377578.1316378493.1316378493.1316378493.1

322.71MB になってる

Firefox 14.0.1 - 2.82GB 送信時

POST http://example.jp/uploader/upload//3253414070 HTTP/1.1
Host: example.jp
User-Agent: Mozilla/5.0 (Windows NT 5.2; WOW64; rv:14.0) Gecko/20100101 Firefox/14.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Proxy-Connection: keep-alive
Referer: http://example.jp/uploader/
Cookie: __utma=228853188.280221657.1314556159.1331915237.1334759080.7; __utmz=228853188.1334759080.7.6.utmccn=(referral)|utmcsr=google.co.jp|utmcct=/imgres|utmcmd=referral
Content-Type: multipart/form-data; boundary=---------------------------26418279386900
Content-Length: -1261380876

負の値

Firefox 14.0.1 - 4.3GB 送信時

POST http://example.jp/uploader/upload//2029255848 HTTP/1.1
Host: example.jp
User-Agent: Mozilla/5.0 (Windows NT 5.2; WOW64; rv:14.0) Gecko/20100101 Firefox/14.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://example.jp/uploader/
Cookie: __utma=228853188.280221657.1314556159.1331915237.1334759080.7; __utmz=228853188.1334759080.7.6.utmccn=(referral)|utmcsr=google.co.jp|utmcct=/imgres|utmcmd=referral
Content-Type: multipart/form-data; boundary=---------------------------762748024099
Content-Length: 702

 -----------------------------762748024099
Content-Disposition: form-data; name="file"; filename="kanaria.rar"
Content-Type: application/x-rar-compressed

Rar!??s??
????????t??`??????????+?|4?@03? ???????????en_windows_7_ultimate_with_sp1_x64_dvd_u_677332.iso??*?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

リクエストボディ付。 "?" はファイルのバイナリで化けてます。 …でまぁ、このボディだけだと 695byte だったりはします^^; なんかの文字のコピペに失敗したのかも…? …とはいえ、他にパラメータ4つぐらいあるハズなんだけどなぁ… 後にパケットが続いたとしても、残り7byteで表現できないしなぁ…

→ やっぱり挙動が怪しい気がする(ぉ

Opera 12.0 - 2.82GB 送信時

POST /uploader/upload//3493308023 HTTP/1.1
User-Agent: Opera/9.80 (Windows NT 5.2; WOW64; U; ja) Presto/2.10.289 Version/12.00
Host: example.jp
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: ja-JP,ja;q=0.9,en;q=0.8
Accept-Encoding: gzip, deflate
Referer: http://example.jp/uploader/
Connection: Keep-Alive
Content-Length: 3033586364
Content-Type: multipart/form-data; boundary=----------kc1nYkz5CKzz7QbXlR4OqI

OK

Opera 12.0 - 4.3GB 送信時

POST /uploader/upload//3639104731 HTTP/1.1
User-Agent: Opera/9.80 (Windows NT 5.2; WOW64; U; ja) Presto/2.10.289 Version/12.00
Host: example.jp
Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
Accept-Language: ja-JP,ja;q=0.9,en;q=0.8
Accept-Encoding: gzip, deflate
Referer: http://example.jp/uploader/
Connection: Keep-Alive
Content-Length: 654
Content-Type: multipart/form-data; boundary=----------0jwScDP2ld1qKmPGYDytPJ

 ------------0jwScDP2ld1qKmPGYDytPJ
Content-Disposition: form-data; name="file"; filename="kanaria.rar"
Content-Type: application/x-rar-compressed


 ------------0jwScDP2ld1qKmPGYDytPJ
Content-Disposition: form-data; name="comment"

iso
 ------------0jwScDP2ld1qKmPGYDytPJ
Content-Disposition: form-data; name="download_pass"


 ------------0jwScDP2ld1qKmPGYDytPJ
Content-Disposition: form-data; name="remove_pass"

test
 ------------0jwScDP2ld1qKmPGYDytPJ
Content-Disposition: form-data; name="code_pat"


 ------------0jwScDP2ld1qKmPGYDytPJ
Content-Disposition: form-data; name="submit"


 ------------0jwScDP2ld1qKmPGYDytPJ--

リクエストボディ付。 ファイルの中身が空っぽです。

Chrome 20.0 - 2.82GB 送信時

POST /uploader/upload//3823057925 HTTP/1.1
Host: example.jp
Connection: keep-alive
Content-Length: 3033586398
Cache-Control: max-age=0
Origin: http://example.jp
User-Agent: Mozilla/5.0 (Windows NT 5.2; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvAM37gHVlSQEpjjA
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: http://example.jp/uploader/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: ja,en-US;q=0.8,en;q=0.6
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.3

OK

Chrome 20.0 - 4.3GB 送信時

POST /uploader/upload//1038647563 HTTP/1.1
Host: example.jp
Connection: keep-alive
Content-Length: 4633355231
Cache-Control: max-age=0
Origin: http://example.jp
User-Agent: Mozilla/5.0 (Windows NT 5.2; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryUbRDMovTgufJzVRM
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: http://example.jp/uploader/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: ja,en-US;q=0.8,en;q=0.6
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.3

OK



おまけ

http パケット解析に Fiddler2 を利用していたのですが、この子 2GB 以上のリクエストには対応していない様子。 ってか .NET が制約持ってる感じ?

↓こんなエラーダイアログが出ちゃいました

http://ir9.jp/hd12/0720_00.png

Fiddler has encountered an unexpected problem. If you believe this is a bug in Fiddler, please copy this message by hitting CTRL+C, and submit a bug report using the Help | Send Feedback menu.

Sorry, the .NET Framework (and Fiddler) cannot handle streams larger than 2 Gigabytes.

Type: System.Exception
Source: Fiddler
   場所 Fiddler.PipeReadBuffer.Write(Byte[] buffer, Int32 offset, Int32 count)
   場所 Fiddler.ClientChatter.ReadRequest()
   場所 Fiddler.Session._executeObtainRequest()
   場所 Fiddler.Session.InnerExecute()
   場所 Fiddler.Session.Execute(Object objThreadState)