JS・PHP・HTML 大きいファイルをアップロード(JSのライブラリは無し)
分割アップロードとか・・・そんなヤツ。ライブラリは使わない。
作成日:2021-11-22, 更新日:2024-03-29
基本
JSのライブラリとかを使えばラク・・・なんだけど、環境や大人の事情によって使えないライブラリの使用がNGというコトもある
やりたいこと
- 大きいファイルをアップ
- その後、form送信
流れ
- 送信ボタンでまずファイルを分割して、アップロード(※ファイルは分割したままでOK)
- 分割アップロードが終わったら、form全体を送信
送信ボタンでまずファイルを分割して、アップロード
「await fetch()」とか使っているが詳細不明。
ajaxでやったほうが理解しやすいけど、時間的な問題でどっかのサイトで見つけたソースをベースにカスタマイズ
分割アップロードが終わったら、form全体を送信
アップされたファイルから何かしたいなら、ココで処理。
サンプル
HTML + JS
<form method="post" action="uploads.php"> <input type="text" name="hoge" /> <input type="file" name="ori_file" /> <input type="button" value="送信" /> </form> <script> let chunk_upload = async function(elm){ let slice_size = 5 * 1024 * 1024; // 分割サイズ(5MB) let file = elm.prop('files')[0]; let size = file.size; let count = Math.ceil(size / slice_size); let postForm = null; let splitData = null; let result = null; let flg_err = false; for (let k=0; k < count; k++) { if ( flg_err ) { break; } splitData = file.slice(k * slice_size, (k + 1) * slice_size); postForm = new FormData(); postForm.append('chunk_file', splitData); // 分割したファイルデータ postForm.append('chunk', k); result = await fetch('chunk_upload.php', { body: postForm, method: 'POST', headers: { Accept: 'application/json' } }).then(res => res.json()) // ← 決め打ちで必要っぽい .then(result => { // ← PHPで出力したJSONはココにいる if ( result.err != undefined && result.err != '' ) { alert(result.err); flg_err = true; } }); await new Promise(res => setTimeout(() => { res(); // ← 詳細不明。コイツがいないとダメっぽい }, 1000)); } if ( !flg_err ) { jQuery('[name="ori_file"]').val(''); // formからfileを削除 $('form').submit(); // 残りをform送信 } return false; } jQuery('[type="button"]').on('click', function(){ if ( jQuery('[name="ori_file"]').val() == '' ) { alert('ファイルを選択してください。'); return false; } chunk_upload(jQuery(jQuery('[name="ori_file"]')[0])); }); </script>
chunk_upload.php
分割されたファイルを任意のトコに保存。
// function exceptions_error_handler($severity, $message, $filename, $lineno) { // 全体で設定済みなら不要 // throw new ErrorException($message, 0, $severity, $filename, $lineno); // } function temporary_chunk_upload() { $result = array( 'err' => '', ); $chunk = (int) $_POST['chunk']; $to_path = __DIR__ . 'uploads'; $fileName = 'chunk' . $chunk . '.txt'; // chunk0.txt、chunk1.txt・・・みたいな感じにしたい $file_path = $to_path . '/' . $fileName; try { // waringも例外に飛ばす // set_error_handler('exceptions_error_handler', E_WARNING); // 全体で設定されているならこのまま if( $_FILES['chunk_file']['tmp_name'] == '' ) { throw new Exception('ファイルを指定してください。'); } $url = $_FILES['chunk_file']['tmp_name']; file_put_contents($file_path, @file_get_contents($url)); // ファイルを合体させるなら上書き設定 } catch (Exception $e) { $result['err'] = $e->getMessage(); } echo json_encode($result); exit; } temporary_chunk_upload();
uploads.php
ファイルのアップが終わったあとのform送信の受け口
// ▼分割したファイルはココの中にいる $from_path = __DIR__ . 'uploads'; // ▼formに入力された値 $post_hoge = $_POST['hoge'];