ホームページ > 記事 > ウェブフロントエンド > tp5+layui を使用した大容量ファイルのアップロードの概要
最初に、ファイルのアップロード サイズを変更するための構成情報を記録します。
php.ini
file_uploads を開きます。 = ON // スイッチが http 経由でファイルをアップロードできるようにし、
# UPLOAD_TMP_DIR // 一時ファイル
UPLOAD_MAX_FILESIZE 20M // アップロードするファイルの最大値アップロード可能
#post_max_size 22M //フォーム POST
max_execution_time 600 //単一の PHP ページの実行が許可される最大時間
max_input_time 600 //単一の PHP ページがデータを受信するのに必要な最大時間 時間、デフォルトは 60 秒
memory_limit 256M //単一の PHP ページの実行中に占有できる最大メモリ、デフォルトは8M
上記の構成サイズを変更することで、許可されるファイルのアップロードを調整できます。 (一部のサーバー構成を調整する必要がある場合もあります)
補足: 413 エラー サーバーが nginx の場合、構成 nginx_conf の client_max_body_size を 24M に変更し、クライアントが送信するパケットを受信するための最大値を設定する必要があります。 http に置くことを忘れずに、サーバーを再起動し、再起動を使用し、リロードは使用しないでください。
次に、ファイルの分割アップロードを実現します。
ファイル HTML input タグのファイルからアップロードするファイルを選択します。 H5 の新しいオブジェクト FileReader を通じて。文字通りの意味のように、FileRaeder オブジェクトはローカル ファイルを読み取るオブジェクトです。 FileReader オブジェクトは、ローカル ファイルを読み取り、base64 エンコードで返すことができます。 (FileReader オブジェクトの使用に関する具体的な情報については、Baidu を参照するか、非常に具体的な次のブログ投稿をお読みください。
実際の開発
最初の試み
入力ファイル タグを通じてファイルを選択します。
FileReader オブジェクトを使用してファイルを読み取ります。
ファイルの Base64 エンコーディングを ajax を通じてサーバーに非同期で送信します。
サーバーはエンコードを受信し、デコードされてファイルに保存されます。
テスト結果は失敗します。ファイルが大きすぎると、エンコードの長さも長くなります。オンライン パラメーターの送信最大数は、非同期 ajax は 8000 バイトです。
2 回目の試行
##最初の試行に基づいて、取得した Base64 エンコードを分割してアップロードします##取得した Base64 エンコード文字列をいくつかの部分に分割し、Number を実行します、ループ内で ajax を呼び出して送信します
データを受信した後、サーバーはデータをデコードし、番号で名前を付けます
すべての小さなファイルを受信した後、バックグラウンド メソッドを呼び出してマージします小さなファイル
テスト結果は失敗しました。アップロードされたファイルが 1G を超えると、ブラウザがクラッシュしました。ファイルを読み取るときにファイルが大きすぎて、ワンタイム エラーによって Base64 エンコーディングが返されたためであるはずです。読み取りが大きすぎるため、ページがクラッシュしました。
3 回目の試行
2 回目の試行に基づいて、ファイルを読み取るプロセス中にバッチで読み取り、ページを回避するエンコーディングを取得することも考えました。一度に大きすぎるファイルを読み込むとクラッシュが発生します。.
ここでは、バッチ読み取りとバッチアップロードを実現するために、H5 の file.slice() を使用してファイルをチャンクに分割する必要があります。
FlieReader オブジェクト Kuai を通じてファイルを読み取ります。
base64 エンコーディングを ajax を通じてサーバーに非同期に送信します。
サーバーはデコードとファイル保存のためのデータを受信します。
テストは次のとおりです。成功し、テストは 4G ファイルをアップロードしました。
(ファイルがセグメント化されているため、大きなファイルをアップロードすると大量の Ajax リクエストが開始され、大量の同時実行が発生し、ページがまたクラッシュします。そのため、時間差リクエストを使用しました。Ajax リクエストの生成速度を遅くします。)
具体的な実装コード
次にコードを投稿します
フロントエンド フレームワーク: layui
バックエンドフレームワーク: tp5
ページコード:
<div class="layui-form-item"> <label class="layui-form-label">视频上传</label> <div class="layui-input-block layui-upload-video-btn"> <ul> <li class="img-upload"> <label></label> <input type="file" class="video-upload-file layui-upload-video-file-btn" name="file"/> <video width="320" height="240" controls style="display: none"> <source src="" type="video/mp4"> <source src="" type="video/ogg"> 您的浏览器不支持Video标签。 </video> <span style="display: none">X</span> <input type="hidden" class="video-link-id" name="video_link_id" value=""> </li> <li>//视频上传会比较久(上传完会有提示)</li> </ul> </div> </div>
js コード:
$('.video-upload-file').on('change',function(){ layer.msg('正在提交视频......'); //隐藏按钮,显示进度条 $('.layui-upload-video').hide(); $('.layui-progress-ads').show(); var loads_video = layer.load(2,{shade: [0.2, '#3a3535']}); //产生加载圈,禁止用户其他操作 var thisFile = $(this); var reader=new FileReader(); var file_size = this.files[0].size; //文件大小 var limit = 8388608; //每次读取文件的大小 // var limit = 1048000; //每次读取文件的大小 var up_count = Math.ceil(file_size/limit); //总上传次数 var type = this.files[0].type.substr(this.files[0].type.indexOf('/')+1); //文件类型 var success_num = 0; //用于存放上传成功的数据的id var check = 1; //防止多次合并 console.log('文件大小:'+this.files[0].size); console.log('文件类型:'+type); console.log('分割上传次数:'+up_count); //分段读取文件 readFile(this.files[0], 0, limit); function readFile(file, num, limit){ // console.log('第'+num+'次:'+num*limit); reader.readAsDataURL(file.slice(num*limit, (num+1)*limit)); reader.onload = function(e){ console.log(reader.result.length); console.log(reader.result); //异步base64的数据传输到服务器 ajax_way(reader.result, name, num+1, thisFile); if((num+1)*limit <= file_size){ readFile(file, num+1, limit); } } } function ajax_way(data,name,num, thisFile){ //避免一次性生成太多的请求 if(num+1 > 60){ // console.log('等待两秒'); sleep(6000); // console.log('等待结束'); } $.ajax({ url: "<?= url('admin/video/up_mfile');?>", type: "POST", data: {video:data,name:name,num:num}, // async:false, //是否采用同步,串行发送请求 success: function (data) { if(data.code == 1){ //上传成功,成功次数加一 success_num++; console.log(num+'完成'); console.log('已完成:'+success_num+'/'+up_count); //计算完成的百分比 var precentage = Math.ceil((success_num/up_count)*100); //更改进度条显示 $('.layui-progress-ads-btn').attr('lay-percent', precentage+'%'); $('.layui-progress-ads-btn').css('width', precentage+'%'); $('.layui-progress-text').html(precentage+'%'); //如果分割文件都上传了则调用接口合并文件 if(success_num == up_count && check == 1){ check = 0; success_num = 0; merge_mfile(name, up_count, thisFile, type); } } }, error:function(e){ console.log('出错了:'+num); //传输出错则重新上传 ajax_way(data, name, num, thisFile); } }); } //合并文件 function merge_mfile(name, count, thisFile, type){ $.ajax({ url:"<?= url('admin/video/merge_mfile');?>", data:{name:name, count:count, type:type}, type:"POST", success:function(data){ if (data.code==1){ layer.close(loads_video); layer.msg('视频提交成功'); thisFile.siblings('.video-link-id').val(data.data); }else{ layer.msg('视频提交异常请重新提交'); //显示按钮,隐藏进度条 $('.layui-upload-video').show(); $('.layui-progress-ads').hide(); //将进度条置零 $('.layui-progress-ads-btn').attr('lay-percent', '0%'); $('.layui-progress-ads-btn').css('width', '0%'); $('.layui-progress-text').html('0%'); //清空已选中的文件 var file = $(".layui-upload-video-file-btn"); file.after(file.clone().val("")); file.remove(); } } }) } function sleep(n) { //n表示的毫秒数 var start = new Date().getTime(); while (true) if (new Date().getTime() - start > n) break; } return false; });
layui の詳細については、# に注意してください。 ##layui の使い方チュートリアル
列.以上がtp5+layui を使用した大容量ファイルのアップロードの概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。