tft每日頭條

 > 科技

 > php怎麼處理ajax表單

php怎麼處理ajax表單

科技 更新时间:2024-08-19 06:11:28

上傳大的附件分為兩種情況,

  1. 可以改變服務器配置;
  2. 不能改變配置;

第2種使用分片上傳

優勢:可以突破服務器上傳大小的限制,可以web存儲上傳到哪一塊了,在浏覽器關閉或者刷新的情況下可以斷點續傳;

劣勢:上傳速度慢,在我本地電腦測試,200M的文件,改變配置按照正常方式上傳大約需要12到15秒,但是使用第2種分片上傳,大約需要40多秒,也就是所需時間是正常上傳的3倍,我測試了for循環同時上傳幾個碎片,電腦直接很卡,點擊别的浏覽器或者文件夾之類的全部是沒有響應,所以放棄了使用循環同時上傳多個;

如果上傳大的文件實現進度條是很有必要的,否則用戶看不到進度會等得不耐煩了。

小的文件隻需要2秒左右,是否有進度條沒有關系。

第一種,在可以改變服務器配置的前提下

php怎麼處理ajax表單(php手把手教你做網站)1

圖1 帶進度條文件上傳

1、配置php.ini

  1. post_max_size post數據默認8M
  2. upload_tmp_dir 文件上傳臨時文件(upload_tmp_dir="E:\temp8.0.11")
  3. upload_max_Filesize 上傳的大小默認2M
  4. max_execution_time 程序超時時間默認30秒

如果上傳的文件比較大,以上4點都需要修改,特别是第2點,盡可能配置,否則上傳最後會比較慢。

2、iis上傳大小限制,可以在web.config直接修改,加入以下代碼

<security> <requestFiltering> <requestLimits maxAllowedContentLength="1073741824" /> </requestFiltering> </security>

<requestLimits maxAllowedContentLength="1073741824" /> 這裡是限制的大小,默認大小忘記了,我這裡設置的是可以上傳1G進行的測試。

3、nginx上傳大小限制

  1. client_max_body_size 2000m; #upload size 随便寫的2000M方便上傳1G大小文件測試
  2. client_header_timeout 300;
  3. fastcgi_connect_timeout 300;
  4. fastcgi_send_timeout 300;
  5. fastcgi_read_timeout 300;
  6. fastcgi_request_buffering off;

我開始想把這些加到location / {}裡邊,提示錯誤client_header_timeout不允許放到裡邊,所以全部加到外邊了,也就是server {}裡邊;

注意下第6點,如果不配置,nginx上傳文件會存到緩存,然後再一點一點傳到upload_tmp_dir的目錄下,導緻上傳所需時間是iis的2倍。

4、html代碼

<tr class=''> <td width="90" align="right" rowspan='2'>超大附件</td> <td> <div class='jdfull '><div class='jdperc'></div></div> <div class='jdtis '>0%</div> <input type='file' id="down_bfule_tpfile" class='inpMain layui-inpu' name='' size='30'><button type='button' class='layui-btn submitpfile' >上傳</button> </td> </tr> <tr class=''> <td> <input type='text' class='inpMain' placeholder='不限大小' style='width:calc(100% - 20px);' value='' name='down_bfule' id="down_bfule" ></td> </tr>

5、css代碼 用來設置進度條

/*進度條*/ .jdfull{width:calc(100%);height:20px;background:#FFF;margin-bottom:10px;border-radius:10px;border:1px solid #DDD;} .jdperc{height:20px;background:#5FB878;width:0px;border-radius:10px;} .jdtis{margin-bottom:10px;}

6、js代碼(jquery使用監聽progress實現進度條功能)

$(".submitpfile").click(function() { var fileext=['rar','ZIP','pdf']; var formData = new FormData(); formData.append("file", $("#down_bfule_tpfile").get(0).files[0]); if (!$("#down_bfule_tpfile").get(0).files[0]) { alert("請選擇要上傳的文件!"); return false }; //判斷擴展名 是否支持上傳 var patharr = $("#down_bfule_tpfile").get(0).files[0].name.split("."); //上傳文件擴展名轉小寫,ZIP zip 2個是同一個文件 var ext = patharr[patharr.length - 1].toLowerCase(); if (fileext.indexOf(ext) < 0) { alert('隻支持' fileext.join(',')); return false; } $.ajax({ url: '處理圖片上傳的url', data: formData, type: "post", dataType: "JSON", contentType: false, processData: false, //監聽progress 實現上傳進度條 xhr: function() { var xhr = new XMLHttpRequest(); xhr.upload.addEventListener('progress', function(e) { console.log(e); //百分比取整 var progressRate = parseInt((e.loaded / e.total) * 100); $('.jdfull .jdperc').css('width', progressRate "%"); $('.jdtis').html(progressRate "%") }); return xhr }, /*進度條結束*/ success: function(result) { if (result.error == "0000") { console.log(result.msg); //上傳完成以後文件地址賦值給文本框,用于表單提交 $("#down_bfule").val(result.msg); } else { //錯誤信息提示 alert(result.msg); return false } //上傳框初始化 var objFile = document.getElementById("down_bfule_tpfile"); objFile.outerHTML = objFile.outerHTML.replace(/(value=\"). \"/i, '$1"') } }) })

7、後端php處理程序

foreach($_FILES as $k=>$v){ $v['name']//文件名稱 $v['size']//文件大小 $v["tmp_name"]//臨時文件名包含了物理路徑E:\temp\文件名 move_uploaded_file($v["tmp_name"],'文件存放路徑(物理路徑 文件名)') }

第二種,不能改變服務器的配置使用分片上傳

php怎麼處理ajax表單(php手把手教你做網站)2

圖2 進度條顯示多少片

html,css不變,隻是改變js,下面是用到的js代碼

代碼1:點擊事件

$(".submitpfile").click(function() { var fileext=['rar','zip','pdf'];//支持格式 var ranksize=1024*1024;//分片每次上傳的大小 1M if (!$("#down_bfule_tpfile").get(0).files[0]) { alert("請選擇要上傳的文件!"); return false }; var patharr = $("#down_bfule_tpfile").get(0).files[0].name.split("."); var ext = patharr[patharr.length - 1].toLowerCase(); if (fileext.indexOf(ext) < 0) { alert('隻支持' fileext.join(',')); return false } var size = $("#down_bfule_tpfile").get(0).files[0].size; var start=true;//是否從第一個開始上傳 var localname=$("#down_bfule_tpfile").get(0).files[0].name; /* 使用localStorage 文件名作文變量存儲 存儲大小,還有上傳了多少片 文件名存放 判斷大小 如果大小也和上傳的文件相同判斷為同一個文件 如果用戶把文件名改成了上傳過的,不加判斷會造成上傳文件錯誤 window.localStorage.getItem 獲取存儲的數據 window.localStorage.setItem 設置存儲的數據 key value window.localStorage.removeItem 移除存儲的數據 json.parse 字符串轉成json格式 */ if(JSON.parse(window.localStorage.getItem(localname))){ var localsize=JSON.parse(window.localStorage.getItem(localname)).localsize; var ranknum=JSON.parse(window.localStorage.getItem(localname)).ranknum; if(size==localsize){ //已經上傳過 但是沒有上傳完,中斷了 start=false; } } if(start==true){ //第一片開始上傳 uploadtp(1); }else{ //存儲的下一片開始上傳 uploadtp(ranknum 1); } })

代碼2:uploadtp方法

function uploadtp(m){ var size = $("#down_bfule_tpfile").get(0).files[0].size; var formData = new FormData(); formData.append("filename", $("#down_bfule_tpfile").get(0).files[0].name); formData.append("size", size); //Math.ceil 向上取整 獲得上傳總得片數 例如:1.1 1.9 都會取整為2,和php的分頁一個性質 rankcount=Math.ceil(size/ranksize); /* uptemp 用于存放 要上傳大小 上傳完多少片 uptemp['ranknum']=m; 上傳完多少片 uptemp['localsize']=size; 上傳文件總得大小,用于判斷要上傳的是否同一個文件 JSON.stringify 數組轉成json字符串 */ var uptemp={}; uptemp['ranknum']=m; uptemp['localsize']=size; window.localStorage.setItem($("#down_bfule_tpfile").get(0).files[0].name,JSON.stringify(uptemp)); /*存儲完成*/ /* $("#down_bfule_tpfile").get(0).files[0].slice 對選擇的文件進行切割 (m-1)*ranksize 起始位置 m*ranksize 結束位置 */ formData.append("photo", $("#down_bfule_tpfile").get(0).files[0].slice((m-1)*ranksize,m*ranksize)); $.ajax({ url: "處理上傳的url", data: formta, type: "post", dataType: "json", contentType: false, processData: false, /* 進度條開始 這是一種豎線方式 監聽progress,監聽每一片的上傳進度 */ xhr: function() { var xhr = new XMLHttpRequest(); xhr.upload.addEventListener('progress', function(e) { console.log(e); var progressRate = parseInt((e.loaded / e.total) * 100); $('.jdfull .jdperc').css('width', progressRate "%"); $('.jdtis').html("總共:<span style='color:red'>" rankcount "</span>片,當前:第<span style='color:red'>" m "</span>片" progressRate "%") }); return xhr }, /*進度條結束*/ success: function(result) { if (result.error == "0000") { $('.jdtis').html("全部上傳完成!"); //上傳完成,清除以前的分片存儲 window.localStorage.removeItem($("#down_bfule_tpfile").get(0).files[0].name); var objFile = document.getElementById("down_bfule_tpfile"); objFile.outerHTML = objFile.outerHTML.replace(/(value=\"). \"/i, '$1"'); $("#down_bfule").val(result.msg) } else if(result.error == "0001") { //0001文件沒有上傳完 需要繼續上傳 uploadtp(m 1); }else{ //php處理返回的錯誤提示 比如長時間沒有刷新頁面,導緻已經退出登陸了 alert(result.msg); return false } } /* 第2種 去掉上邊進度條開始 到結束的代碼,使用下面的success 代替上邊的success 根據上傳了多少片除以總數 顯示當前的百分比 var progressRate=parseInt((m / rankcount) * 100); */ /* success: function(result) { if (result.error == "0000") { var progressRate=100; $('.jdfull .jdperc').css('width', progressRate "%"); $('.jdtis').html("全部上傳完成!"); window.localStorage.removeItem($("#down_bfule_tpfile").get(0).files[0].name); var objFile = document.getElementById("down_bfule_tpfile"); objFile.outerHTML = objFile.outerHTML.replace(/(value=\"). \"/i, '$1"'); $("#down_bfule").val(result.msg) } else if(result.error == "0001") { var progressRate=parseInt((m / rankcount) * 100); $('.jdfull .jdperc').css('width', progressRate "%"); $('.jdtis').html(progressRate "%"); //0001文件沒有上傳完 需要繼續上傳 uploadtp(m 1); }else{ //php處理返回的錯誤提示 比如長時間沒有刷新頁面,導緻已經退出登陸了 alert(result.msg); return false } } */ }) }

php後端處理程序

$filename=input('post.filename');//原始文件名 $size=input('post.size');//原始文件大小 //創建存放的文件夾 foreach($_FILES as $k=>$v){ //$v["tmp_name"]臨時文件 含路徑 $images_dir = '/public/upload/file/'.date("Ymd")."/"; if (!file_exists(ROOT_PATH."".$images_dir)) { mkdir(ROOT_PATH."".$images_dir,0777); } $name = explode(".", $filename); //将上傳前的文件以“.”分開取得文件類型 支持png jpg gif $imgtype=strtolower($name[count($name)-1]);//類型轉成小寫 $newname=date("YmdHis".rand(10000,99999)).".".$imgtype;//新的文件名 //file_put_contents 追加 注意有FILE_APPEND,不加的話會覆蓋原來的 //file_get_contents讀取内容 file_put_contents(ROOT_PATH.$images_dir.$filename,file_get_contents($v["tmp_name"]),FILE_APPEND); //判斷大小 是否已經上傳完成 if(filesize(ROOT_PATH.$images_dir.$filename)>=$size){ rename(ROOT_PATH.$images_dir.$filename,ROOT_PATH.$images_dir.$newname); exit( json_encode(array('error'=>'0000','msg'=>$images_dir.$newname),JSON_UNESCAPED_UNICODE)); }else{ exit( json_encode(array('error'=>'0001'),JSON_UNESCAPED_UNICODE)); } }

說明:

  1. 返回代碼0000上傳完成,0001未完成繼續上傳,其他錯誤提示;
  2. 分片上傳不能使用move_uploaded_file,而是使用file_put_contents追加
  3. file_put_contents追加用法file_put_contents("物理路徑 文件名","追加的信息",FILE_APPEND);

nginx上傳文件很慢

處理辦法:關閉 fastcgi_request_buffering,如果不關閉,上傳所需時間至少是iis的2倍;

具體操作:編輯nginx.conf,

server {

fastcgi_request_buffering off;

}

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved