- ベストアンサー
大きいファイルのアップロードについて
PHPで大容量のファイルのアップロードされた場合の処理について教えてください。 PHPのアップロードの上限設定はphp.iniで設定できるのは分かります。 今回の質問は、FacebookやCookpad等で画像をアップロードをすると即座にアップロードされますが、どのように実現しているのでしょうか。複数人で画像等をアップロードするようなサイトの場合、アップロードしている間プロセスが占有されるため、できる限り早く処理できるとよいと考えております。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
もちろんバイトストリームを自分で処理してファイルに追記していくのを手動でやってもいいですが、PHPにはそういったローレベルの操作をサポートしている「クラス」は存在しません。古典的に「関数」を使って書きにくいコードを書くしかないです。 それぐらいならば $_FILES や $_SESSION といったPHP言語レベルでサポートされたファイルアップロード機能(テンポラリファイル生成機能)を利用すべきだと私は考えますね。実際こっちのほうがメモリ消費も少ないと思います。PHPの変数の最小単位(zval構造体)は、PHPのもとになっているC言語の変数の最小単位よりも遥かに大きな記憶領域を必要とします。
その他の回答 (4)
えーっと…まさにそのことについてのリンクをさっきから掲載しているんですが…(汗 メモリ上にではなくテンポラリファイルとして生成されます。これは通常のアップロードであってもセッションを利用したアップロードであっても同じです。ちゃんと記事に書いてあるので読んでください。 >> ["tmp_name"]=> >> string(22) "/private/tmp/phpeMGDne" >> ["start_time"]=> >> int(1323713434) >> ["bytes_processed"]=> >> int(155540) こういうところを見て「テンポラリファイルに徐々に書き込まれていく」っていうのを察してほしいですね…
PHP5.4以降のセッションを利用したアップロードを行う場合、一般的なファイルのアップロード処理方法とは大きく異なります。先ほどの回答で記載したリンク先で具体的に分かりやすく解説されているのでそちらが参考になるかと思いますが… 【通常のアップロード】 Qiita - ファイルアップロードの例外処理はこれぐらいしないと気が済まない http://qiita.com/mpyw/items/939964377766a54d4682 こちらではそのままechoして結果を表示していますが、JavaScriptに受け取らせるには header('Content-Type: application/json; charset=utf-8'); echo json_encode($message); のようにしてJSON形式にします。もしクロスドメインである場合は header('Content-Type: application/javascript; charset=utf-8'); echo 'callback(' . json_encode($message) . ')'; のようにしてJSONP形式にする方法も候補として上がるでしょう。 【セッションを利用したアップロード】 こちらの方法は通常の方法と完全に異なります。通常の方法ではファイルが全てアップロードされるのを待ってからスクリプトが1回実行されるだけでしたが、こちらの方法ではアップロードが終わる前にPHPのスクリプトが開始されます。 ・JavaScript側でアップロードリクエストを開始 ↓ ・PHP側でセッションへ進捗情報の格納を開始 ・PHP側から「Set-Cookie: PHPSESSID=xxxx」としてセッションクッキーが送られるのでJavaScript側はこれを記憶しなければならない ・PHP側から進捗情報をJSONまたはJSONPで返し、JavaScript側でこれをパースして表示を行う ↓ ・Cookieをセットして2回目のリクエストを行う ・PHP側から進捗情報をJSONまたはJSONPで返し、JavaScript側でこれをパースして表示を行う ↓ ・Cookieをセットして3回目のリクエストを行う ・PHP側から進捗情報をJSONまたはJSONPで返し、JavaScript側でこれをパースして表示を行う ↓ (以降繰り返し) これを一定ミリ秒ごとにJavaScript側から繰り返し実行し続ければ実現できます。
補足
解説ありがとうございます。説明不足ですみません。 気にしているのは、PHP側のファイル処理の仕方です。 大容量のファイルをアップロードされた場合、サーバにアップロード完了するまでメモリ上に残していると問題があると思いました。最悪の場合PHPのプロセスだけでメモリを食いつぶすこともありえそうに思えました。 アップロード処理はどのように実装しているのでしょうか(すべきでしょうか)。 できれば,参考になるものを紹介していただけると助かります。 ※Javaのファイルストリームようにバッファサイズを超えたらファイル出力するような処理を実装すべきではないかと考えております。
PHP5.4以降であれば、セッションを利用してちょっと気持ち悪いことも出来ます↓ http://d.hatena.ne.jp/anatoo/20111213/1323714933
PHPで即座にアップロードじゃなくて、JavaScriptを使って非同期でアップロードしてるだけです。もちろんサーバー側にはJavaScriptからの通信を受け付けるPHPスクリプトが控えていますが、ユーザーが見るものとは別物で、HTMLを表示したりはしません。JSONでレスポンスを返すだけです。 こういうの参考になるんじゃないでしょうか↓ http://webdelog.info/2013/03/web/javascript/dropzonejs/
補足
回答ありがとうございます。 非同期についてはわかりましたが、非同期を受けるサーバ側はどのような処理をしているのでしょうか。 非同期で受けるサーバ側のファイルアップロードの処理はどのようにすべきなのでしょうか。 PHPで受け取ってファイル出力する方法でよろしいのでしょうか。 ※ファイル出力は受信しながら、ストリーム処理をすればいいのでしょうか(よく分かっておりません)。 大きいファイルのアップロードの定石はないのでしょうか。
お礼
>>PHPにはそういったローレベルの操作をサポートしている「クラス」は存在しません。 理解不足ですみませんでした。 教えていただいたようにPHP5.4 アップロード進捗の取得を使えばよいことでようやく納得しました。 色々な言語を使っていたり、詳しいことが分かっていなかったりして、 分かりづらい質問ばかりで申し訳ありませんでした。 アップローダについて悩んでおりましたが、解決です。 ありがとうございました。 それにしても最近のSNSはやっぱり凄いですね。