檢視 Ajax 的原始碼
←
Ajax
跳轉到:
導覽
、
搜尋
根據以下的原因,您並無權限去做編輯這個頁面:
您剛才的請求只有這個使用者組的使用者才能使用:
使用者
你可以檢視並複製本頁面的原始碼。
===HTTP 中的 Content-Type: multipart/form-data=== 常見的傳輸格式: #Content-Type: application/json 代表請求內容是 JSON #Content-Type: image/png 代表請求內容是圖片檔 #Content-Type: multipart/form-data 使用 (RFC7578) 規範,用一個請求傳送複數個資料格式,主要用於表單或實作檔案上傳。可以用 HTML 的 form 標籤指示 enctype='multipart/form-data' 屬性(配合 Submit),或 JavaScript 的 FormData 類別(配合 onclick)。 #*multipart/form-data 也是 HTTP 請求的一種 #*只要符合格式不用瀏覽器也可以發送請求 #*請求只是將一坨二進制數傳至伺服器,檔案內容必須在伺服器端解析 #表單當中使用 GET 方法送出,那麼所有表單的內容都以 url encoded 的方式被傳送。HTML 點擊 Submit 按鈕後會變成「請求目的地?name=變數值&file=變數值」,就算 enctype 指定 multipart/form-data 還是會以「 application/x-www-form-urlencoded」的形式送出。 以下先看瀏覽器發送的一個 HTTP POST multipart/form-data 請求:<pre>POST 目的地 HTTP/1.1 Host: localhost:3000 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryFYGn56LlBDLnAkfd User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36 ------WebKitFormBoundaryFYGn56LlBDLnAkfd Content-Disposition: form-data; name="name" Test ------WebKitFormBoundaryFYGn56LlBDLnAkfd Content-Disposition: form-data; name="file"; filename="text.txt" Content-Type: text/plain Hello World ------WebKitFormBoundaryFYGn56LlBDLnAkfd--</pre> '''boundary 的作用與格式:''' #指示每個資料的界限在哪裡 #boundary 的格式: #*開頭是兩個 hypen #*總長度在 70 以內(不包含 hypen 本身) #*只接受 ASCII 7bit #*最後一個 boundary 則會再以兩個 hypen 當作結尾 #boundary 之下的處理: #*Content-Disposition: form-data; name="欄名"<br/>空白行<br/>欄位內容 #*如果是檔案:<br/>Content-Disposition: form-data; name="欄名"; filename="檔名"<br/>Content-Type: text/plain<br/>空白行<br/>欄位內容(同時也是檔案內容) #*如果是圖片檔或是其他非文字檔(舉 png 圖檔為例):<br/>Content-Disposition: form-data; name="file"; filename="image.png"<br/>Content-Type: image/png<br/>空白行<br/>圖檔二進制內容 ===FormData 類別=== ===檔案上傳程式範例=== ====(一)無 form 標籤==== #不翻頁 #無法顯示後台程式的回應 '''前台程式''' <pre><!DOCTYPE html> <html> <head> <title> Ajax JavaScript File Upload Example </title> </head> <body> <!-- HTML5 Input Form Elements --> <input id='fileupload' type='file' /> <button onclick='uploadFile()'> Upload </button> <!-- Ajax JavaScript File Upload Logic --> <script> async function uploadFile() { let formData = new FormData(); formData.append('file', fileupload.files[0]); await fetch('./upload.php', {method: 'POST',body: formData}); alert('The file has been uploaded successfully.'); } </script> </body> </html></pre> 說明: #表單元素沒有 form 標籤、沒有 action 指示,完全靠 javascript 的 fetch 指示出被請求的後台程式,執行時也不會將後台程式的回應顯示取代目前的頁 #兩個表單元素:一個負責讓使用者選上傳檔,另一個負責驅動 javascript 的 uploadFile() 函式 #*前台的 <button> 與 <input type='button'> 等效,前者可以夾圖,後者只能表現按鈕上的字 #*type='file' 不需要 name 屬性,只須要 id 屬性讓 javascript 叫用 #*button 更是連 id 屬性都不用,只要可以 onclick 就行 #uploadFile() 是一個非同步函式,其中的 fetch 動作,須等伺服器處理完才能繼續往下走 #async 和 await 相搭配,後者指出要等伺服器處理完的非同步動作。可以使得本應移到程式碼的最後方,等到所有的原始碼運行完以後才會執行的非同步的事件,如同步事件一樣先被執行: #*async function 用來定義一個非同步函式,讓這個函式雖為非同步,但其內部以「同步的方式」運行「非同步程式碼」。 #*await 則是可以暫停非同步函式的運行(中止 Promise 的運行),直到非同步動作進入 resolve 或 reject,當接收完回傳值後繼續 #後送到 $_FILES 通道的變數名由 append 指定,與 input 的 name 屬性無關 #後送到 $_FILES 通道的檔案實體數據,由 input 的選擇動作決定,所以 <input type='file'> 要留 id 屬性 #fileupload 和 document.getElementById('fileupload') 等效 #let 宣告的變數生命週期只在區塊 {…} 之內 #formData.append(欄位, 欄值); #fetch(後送請求目地的,後送選項)<br/>後送選項是一個物件,包含怎麼後送、後送什麼兩個項 #注意時間, alert('The file has been uploaded successfully.'); 會等檔案上傳完才執行 '''對應的後台程式 upload.php''' <pre><?php /* Get the name of the uploaded file */ $filename = $_FILES['file']['name']; /* Choose where to save the uploaded file */ $location = './upload/'.$filename; /* Save the uploaded file to the local filesystem */ if(move_uploaded_file($_FILES['file']['tmp_name'],$location)){ echo 'Success'; }else{ echo 'Failure'; } ?></pre> 說明: #將上傳檔放到 ./upload/ 路徑下 #並以 echo 回應成功或失敗,但此回應不會反映在前台程式執行上,因為前台沒有要處理回應 '''整合前後台程式為:''' <pre><?php // 前置處理 if(isset($_FILES['file']['name'])){ if(move_uploaded_file($_FILES['file']['tmp_name'],'./上傳資料夾/'.$_FILES['file']['name'])){ echo 'Success'; }else{ echo 'Failure'; } }else{ $str="<!DOCTYPE html> <html> <head> <title> Ajax JavaScript File Upload Example </title> </head> <body> <input type='file' id='fileupload' /> <button onclick='uploadFile()'> Upload </button> <!--<input type='button' name='button' value='Upload' id='upload-button' onclick='uploadFile()'/>--> <script> async function uploadFile() { let formData = new FormData(); alert(fileupload); formData.append('file',fileupload.files[0]); await fetch('".$_SERVER['PHP_SELF']."',{method:'POST',body:formData}); alert('The file has been uploaded successfully.'); } </script> </body> </html>"; echo $str; } ?></pre> ====(二)無 form 標籤,用 fetch 後送,將後台回應塞入 Div==== <pre><?php // 前置處理 if(isset($_FILES['file']['name'])){ if(move_uploaded_file($_FILES['file']['tmp_name'],'./上傳資料夾/'.$_FILES['file']['name'])){ echo 'Success'; }else{ echo 'Failure'; } }else{ $str="<!DOCTYPE html> <html> <head> <title> Ajax JavaScript File Upload Example </title> </head> <body> <input type='file' id='fileupload' /> <button onclick='uploadFile()'> Upload </button> <!--<input type='button' name='button' value='Upload' id='upload-button' onclick='uploadFile()'/>--> <script> async function uploadFile() { let formData = new FormData(); formData.append('file',fileupload.files[0]); await fetch('".$_SERVER['PHP_SELF']."',{method:'POST',body:formData}).then((response)=>{return response.text();}).then((responseText)=>{document.getElementById('list').innerHTML=responseText;}); } </script> <div id='list' name='list'></div> </body> </html>"; echo $str; } ?></pre> 說明: #fetch 之後取得回應,回應是一個物件(object),然後用 then 方法處理這個物件 #(response)=>{return response.text();}:將回應物件代入變數 response ,然後執行 {…} 。執行內容就是:對 response 取方法 text() 再返回。 #其返回物是一段文字,,然後再用 then 方法處理這個返回物 #(responseText)=>{document.getElementById('list').innerHTML=responseText;}:將返回物文字片段塞入 ID 為 list 的標籤中。 ====(三)無 form 標籤,不用 fetch 而改用 ajax 後送,將後台回應塞入 Div==== <pre><?php // 前置處理 if(isset($_FILES['file']['name'])){ if(move_uploaded_file($_FILES['file']['tmp_name'],'./上傳資料夾/'.$_FILES['file']['name'])){ echo 'Success'; }else{ echo 'Failure'; } }else{ $str="<!DOCTYPE html> <html> <head> <title> Ajax JavaScript File Upload Example </title> </head> <body> <input type='file' id='fileupload' /> <button onclick='uploadFile()'> Upload </button> <!--<input type='button' name='button' value='Upload' id='upload-button' onclick='uploadFile()'/>--> <script> var ahr; if(window.XMLHttpRequest){ahr=new XMLHttpRequest();} else{ahr = new ActiveXObject('Microsoft.XMLHTTP');} function uploadFile() { var formData = new FormData(); formData.append('file',fileupload.files[0]); ahr.open('POST','".$_SERVER['PHP_SELF']."',true); ahr.onreadystatechange=function(){ if(ahr.readyState==4 && ahr.status==200){ document.getElementById('list').innerHTML=ahr.responseText; } } ahr.send(formData); } </script> <div id='list' name='list'></div> </body> </html>"; echo $str; } ?></pre> 說明: #造 ajax 請求物件 ahr #用 ahr.send(formData) #使用 FormData 後,會將 request 的 Content-Type 設定為「multipart/form-data」 ====(四)用 iframe 配合 target 使 form 後送不翻頁==== <pre><?php // 前置處理 if($_POST['button']=='更新'){ $filename = $_FILES['f']['name']['etTest']['ABC']['fileName']; if(move_uploaded_file($_FILES['f']['tmp_name']['etTest']['ABC']['fileName'], "./upload/".$filename)){ echo 'Success'; }else{ echo 'Failure'; } }else{ $str="<!DOCTYPE html> <html> <head> <meta charset='UTF-8'/> <title> Ajax JavaScript File Upload Example </title> </head> <body> <!-- HTML5 Input Form Elements --> <form target='list' enctype='multipart/form-data' name='col_form' id='col_form' method='post' onsubmit='return xoopsFormValidate_col_form();' > 路徑: <select size='1' name='f[etTest][ABC][path]' id='f[etTest][ABC][path]'> <option value='1'>丁丁</option> <option value='2'>丁禾</option> </select> <input type='checkbox' name='f[etTest][DEF][]' id='f[etTest][DEF][1]' value='1'/> <input type='checkbox' name='f[etTest][DEF][]' id='f[etTest][DEF][2]' value='2'/> 請選檔: <input type='file' name='f[etTest][ABC][fileName]' id='f_etTest_ABC_fileName'/> <button name='button' value='更新' onclick=\"uploadFile('col_form','list');\"> 更新 </button> </form> <!-- Ajax JavaScript File Upload Logic --> <script> async function uploadFile(formID,divID){ let formData = new FormData(document.getElementById(formID)); await fetch('".$_SERVER['PHP_SELF']."', {method: 'POST',body: formData}).then((response) => {return response.text();}).then((responseText)=> {document.getElementById(divID).innerHTML=responseText;}); } </script> <iframe id='list' name='list'></iframe> </body> </html>"; echo $str; } ?></pre> ====(三)用 ajax 不用 fetch==== <pre><body> <form> <label for="">上傳檔案</label> <input type="file" id="picture" /> <input type="button" value="確認提交" onclick="confirm()"> </form> <script> function confirm(e){ var xmlHttp; if(window.XMLHttpRequest){ xmlHttp = new XMLHttpRequest(); }else{ xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } //構造FormData物件 var formData = new FormData(); //新增非檔案資料 formData.append("username","123456"); formData.append("password","67890"); //新增檔案資料 formData.append("picture",document.getElementById("picture").files[0]) //使用POST方法傳送資料 xmlHttp.open("POST","/imageUpload",true); xmlHttp.send(formData) //返回的資料 xmlHttp.onreadystatechange=function(){ if (xmlHttp.readyState==4 && xmlHttp.status==200){console.log(xmlHttp.responseText);} } } </script> </body></pre> 已後送: <pre>{ username:123456, password:67890, picture:檔案資料(其實這裡是將檔案轉換為二進位制了) }</pre> 使用FormData後,會將request的Content-Type設定為 <pre>“multipart/form-data;boundary=----" 一段隨機的字母;</pre> 上面的boundary正如字面的意思一樣,就是一個分界的意思,分開每一個鍵值對資料,具體的資料格式為 <pre>--boundary(換行) Content-Disposition:form-data;name=“資料的鍵”(換行) \r\n(換行) 資料的值(“換行”)</pre> 每一個boundary的前面要加兩個“-” 對於檔案的資料格式為: <pre>--boundary Content-Disposition:form-data;name="username" \r\n 123456 --boundary Content-Disposition:form-data;name="password" \r\n 67890 --boundary Content-Disposition:form-data;name="picture";filename="上傳的檔名" \r\n Content-Type:image/jpeg; 對圖片進行二進位制編碼後的資料 --boundary--</pre>
返回到
Ajax
。
導航
個人工具
登入
名字空間
頁面
討論
變換
檢視
閱讀
檢視原始碼
檢視歷史
動作
搜尋
導覽
首頁
近期變動
隨機頁面
使用說明
工具箱
連入頁面
相關頁面修訂記錄
特殊頁面
頁面資訊