no-cacheこれで完璧かと思うと決してそうではなかった。no-cache"の意味は、サーバーに再度有効か否かを問い合わせることなくキャッシュを使ってはいけないよという程度の意味だったのだ。Modifiedと答えている。ファイルそのものが更新されたか否かという話だけで、ヘッダーがダウンロード指定に変更されたことなど全く無視されている。それではとさらに強力なやつで試してみる。no-storeこれだと一切キャッシュすることをを許可しない。実際いったん写真を表示しておいてダウンロード指定を入れ、再度アクセスするとちゃんとダウンロードされる。最初これを使うとダウンロードの中断再開はできないかもしれないと思っていたがそれもちゃんとできる。no-storeこれだとファイルタイプも正しいものが送出され、仮にPC側でそのまま開くにしても最適なアプリケーションが選ばれる。私の場合は上流でキャッシュ指示した打ち消しも必要。no-store</FilesMatch>とにかくダウンロードを確実に実行させるには絶対にキャッシュさせてはならない。これでいちおう.htaccessによって強制ダウンロードさせることはできるようにはなったが、apacheのIndex機能を使ってのファイルのリスト表示に多少不満があった。大きなのは、ファイルの簡単な説明みたいなことを表示したかったということ。phpスクリプトでファイル名の表示とダウンロードを実行させることにした。以下、その中でいろいろ検討してわかったこと。書き方はもうphpスクリプトでの表現になっています。application/octet-stream');ファイルタイプ(Content-Type)はなるべく正確に出力しましょう。これによりダウンロードダイアログの「表示する」あるいは「アプリケーションで開く」の起動アプリケーションが正しく決定されますし「不明なファイル」と表示されることもなくなります。(実際はoctet-streamとしても多くのブラウザは拡張子やファイルの中身からとにかくファイルタイプを決めようとはしますが。)phpからダウンロードさせる場合httpサーバーはこのめんどうを見てくれませんから、拡張子などから自分で決める必要があります。今回はファイルタイプのリストをつくり、それを参照して決めるようにしました。独自のあるいは規格化されていない部分もかなりあるようですが、普通使われるファイルなら特に問題はなさそうです。必要なら追加すればいいし。filename="'.$filename.'"');ヘッダーを.htaccessに書いてapacheにダウンロードを任せる場合ファイル名の指定はいりませんが(apacheが補填してくれます)、phpから送る場合は必要です。書かないとバッファーIDか何かわけのわからない記号になってしまいます。検索ロボットに対しダウンロード用ファイルに対する活動の抑制は入れるべきです。htmlファイルに対しこれをしておかないと、サンプルとして書いたアドレスやファイルへのアクセスが行われエラーになります。書いておけば写真等がさらされるのがある程度防げます。現在対応しているロボットはgoogle,yahooなど一部のようですので、別途robots.txtなどでもガードしておいた方がいいと思われます。noindex,nofollow,noarchive');キャッシュコントロール.htaccessによる方法のところで前述したようにこれは必須です。世にいろいろ言われているように、このブラウザにはこれ効かないとかいうのがあるようで、とりあえず以下のを書いておきました。no-store,no-cache,must-revalidate,post-check=0,pre-check=0');部分ダウンロード相当大きいファイルをダウンロードさせる場合以外は必要はないけれど、いちおう部分ダウンロードにも対応させてみる。Accept-Rangesこれは部分ダウンロード(ダウンロードの中断→再開の際などにまだダウンロードしていない部分だけを指定してダウンロードするなど)を受け入れるか否かの指定。bytes');この場合当然部分データを要求されたらそのデータを部分ダウンロードの規格に沿って送出するようにプログラムを書いておかなくてはいけない。bytes以外の単位は規格化されておらず、単位は実質bytesしかない。bytes'を書いているサイトをいくつか見つけたが、おおかたどこからか拾ってきてそのまま書いたものだろう。データが変更されていたりして部分ダウンロードが意味をなさないとサーバーが判断した場合などにはすべてのデータを送り直すというのは正しい対応のようだから、実際はダウンロードが最初からやり直しになるだけでダウンロード失敗といった事態にはならないとは思うが。.htaccessでhttpサーバーにダウンロードを任せる場合には部分ダウンロード用のモジュールが入っていてそれが有効になっているかどうかで自動的に送出されるだろうからいらないと思う(たぶん)。HTTP_RANGE部分ダウンロードが要求された場合、$_SERVER['HTTP_RANGE']に以下のようなダウンロード範囲の指定値が入ってくる。","で区切って複数指定もありうる。bytes=1000-2000bytes=1000-bytes=-20001番目と2番めは直感的に問題はない。1000バイト目から2000バイト目までと、1000バイト目から最後まで。問題は-2000の場合。直感的には最初から2000バイト目まで(0-2000と同じ)と思うだろうが、そうではない。これは最後の2000バイトの要求。データが5000バイトあったら3000-4999と同じ。これを0-2000と解釈してプログラムを書いて公開しているサイトが実際にあって最初あやうくそれを鵜呑みにしてしまうところだった。こんなリクエストはめったにないとは思うが、もしあったらバイト数はちゃんと一致しているのでエラーにもならず全く変なデータを正しいものとして渡してしまうことになる。画像みたいなものならともかく、プログラムだったら何が起こるかわからない。いったところで、スクリプトを書いてdownloadフォルダに設置したのでした。スクリプトもここに置いてあります。今回のスクリプトではフォルダごとダウンロードするのには対応していません。都度アーカイブしてダウンロードさせるのは余計な負荷がかかりますし、先にアーカイブファイルを作って置けばいいだけなので。必要を感じたらやることにしましょう。