Logicky Blog

Logickyの開発ブログです

cakePHP 2.3 アップロード ダウンロード

FileBinderは便利だった。これはアップロードを簡単にできるようにするプラグインで、アップロードしたファイルを閲覧したりダウンロードしたりするのも超簡単にヘルパーを使って出来るようになっている。大変有り難い機能である。ノーベル平和賞を個人的にはさしあげたい。

しかしながら、FileBinderでファイル取り扱いに関する全てが解決できるわけではない。そこがFileBinderがノーベル平和賞を受賞できない所以なのかもしれない。

FileBinderですら解決できない事象とは一体どのような状態であろうか?

例えば、アップロードせずにサーバ内で生成したファイルを取り扱う場合などである。 私は今サーバで生成したPDFファイルをダウンロードさせたいのだがいまいち仕組みが分からないなあと思ったのである。

ダウンロードとはなにか?

そもそもダウンロードとはなんだろうか?WEBサーバにおかれているファイルをインターネットを経由してクライアントに送ってあげることである。クライアントは大体ブラウザを通してこのリクエストをしてくるのである。ブラウザに対してリクエストされたファイルをレスポンスするのがダウンロードである。 ということはレスポンスのヘッダにこれはPDFファイルですよとかが書いてあって、文章の代わりにファイルが一緒にくっついていくのであろうか?? 私はこれが分かっていないのだ。

世の中にはテキストデータとバイナリデータというのがあって、テキストデータも本当はバイナリデータなんだけど世の中では区別されることが多いのである。バイナリとは2進数のことで、コンピュータは2進数のみ理解できるわけで、AKB48の写真もコンピュータにとっては残念ながら2進数の集合体でしかないのである。2進数は単なる数値なのであり、コンピュータは実際的にはテキストファイルもバイナリの集合体としてしか見ていないのである。ということはテキストファイルだろうが、バイナリファイルだろうが、レスポンスはいわゆるテキストベースで来るということであろうか?HTMLであれば可読状態でレスポンスが記述される一方、バイナリの場合は不読な2進数の羅列が記述されるのであろうか?もしそうだとすると、クライアント側でそれを可読状態に復元する必要がある。

そもそもよく使われるimgタグのリクエスト・レスポンスの挙動を確認すれば一発で理解できるのではないかと思った。

ないんだけど、このページとかみるとやっぱりファイルの内容を読んで、そのままレスポンスボディーに書いているからそういうことなんだろう。だから俺はajaxでやろうとしても返ってくるのは意味不明なテキスト文字の羅列だったのだな。ということはcakePHPでつくっていたコード自体も大体あってたんだろう。ajaxでそのまま実現するには、この不読文字を可読する必要があるがそんなことできるのかな。スーパー間違っていたらコメントを記載していただければ幸いでございます

ちなみに、このサイトに、こうやって書いてある。

W3Cのサイトを参照すると、xmlHttpRequestのレスポンスは、テキストベースのレスポンス(responseText)か、XMLベースのDOMオブジェクトでのレスポンス(responseXML)の2つである。そのため、エクセルやパワーポイントファイルダウンロードのレスポンスをハンドリングできない。

だからajaxで全部やろうと思っても無理なんだな。ブラウザで普通にアクセスしてレスポンスを受け取るしかないらしい。単純にtarget="_blank"で新たなページ宛にダウンロード用urlにgetリクエストすればいいのかな。パラメータでIDとかファイル名とかを渡すのかな。

追記:2013年6月16日 6:14

おはようございます、cakePHPのPDFダウンロードができました! target_blankも不用みたいだな。

public function download_bill($job_id=null){
    if($job_id){
        $path = $this->bill_path;
        $path .= $job_id;

        $dir = new Folder($path);
        $files = $dir->read(true, false, true);

        if(isset($files[1][0])){
            $path = $files[1][0];
            $file_name = basename($path);

            $this->autoRender = false;
            $this->response->file($path,array('download'=>true));
            $this->response->download($file_name);
        }
    }
}