Android ブラウザでのダウンロードは 2 度ベルを鳴らす

header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename=' . $filename);
header('Content-Transfer-Encoding: binary');

PHP で書くと上記のようなヘッダー出力(抜粋)でファイルをダウンロードさせることができるけど、Android のブラウザでこいつを実行するとどういうわけか「ダウンロードに失敗しました」と通知が出てしまうケースに見舞われた。しかもあるサーバー環境では成功し、あるサーバー環境では失敗するといった環境に依存する状況。

Android 何なのサ!! と怒りつつ失敗するサーバーでアクセスログを調べてみたところ、ダウンロードプログラムの実行時に同じパスに対して以下のように二回アクセスが来ていた。

xxx.xxx.xxx.xxx - username [20/Sep/2012:14:16:37 +0900] "GET /path/to/download HTTP/1.1" 200 644895 "" "Mozilla/5.0 (Linux; U; Android 4.0.4; ja-jp; Galaxy Nexus Build/IMM76K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"

xxx.xxx.xxx.xxx - - [20/Sep/2012:14:16:37 +0900] "GET /path/to/download HTTP/1.1" 401 401 "-" "AndroidDownloadManager"

一度目は Android のブラウザから、二度目は AndroidDownloadManager というクライアントから。ちゃんと意識してなかったけど、Android でのファイルのダウンロードはブラウザから AndroidDownloadManager に処理が委譲されてバックグラウンドで実行されるようになっていた。

ダウンロードに失敗するサーバーでは Basic 認証が掛かっていて、ブラウザから AndroidDownloadManager に処理は委譲されても認証情報までは受け継がれないため、AndroidDownloadManager からのアクセスで 401 エラーが返っていたのが原因だった。

Last updated on July 8, 2015