ไม่ว่าจะเป็น PHP หรือสคริปต์ฝั่งเซิร์ฟเวอร์อื่น ๆ พวกเขามีฟังก์ชั่นการอัปโหลดไฟล์ซึ่งค่อนข้างง่ายต่อการใช้งาน การใช้ JavaScript เพื่อร่วมมือการอัปโหลดไฟล์ AJAX สามารถรับรู้ได้ แม้ว่า jQuery นั้นไม่ได้ให้ฟังก์ชั่นที่ง่ายขึ้น แต่มีปลั๊กอินจำนวนมากที่สามารถนำไปใช้ได้ ในหมู่พวกเขา ajaxfileupload.js จัดทำโดย phpletter.com เป็นปลั๊กอินที่มีน้ำหนักเบาและวิธีการเขียนนั้นคล้ายกับวิธีการทั่วโลก $ .post () ที่จัดทำโดย jQuery และใช้งานง่ายและใช้งานง่าย
อย่างไรก็ตามปลั๊กอินนี้ง่ายเกินไป นอกเหนือจากการจัดหาพา ธ เพื่ออัปโหลดไฟล์แล้วไม่สามารถผ่านค่าเพิ่มเติมไปยังเซิร์ฟเวอร์พื้นหลังได้ ดังนั้นฉันแก้ไขสคริปต์และเพิ่มพารามิเตอร์วัตถุข้อมูล
1. หลักการ
ฉันใช้ PHP เป็นสคริปต์ฝั่งเซิร์ฟเวอร์ที่นี่ หนังสือเกือบทุกเล่มที่มี PHP น้อยกว่าจะกล่าวถึงวิธีการใช้เมธอด move_uploaded_file () เพื่ออัปโหลดไฟล์ฉันจะไม่เข้าไปดูรายละเอียดที่นี่ สิ่งที่ฉันต้องการจะพูดคือการใช้หลักการของการอัปโหลด Ajax
เนื่องจากฉันใช้ไลบรารี jQuery เมื่อฉันคิดถึง Ajax ปฏิกิริยาแรกของฉันคือลองใช้วิธี $ .post () ใช้แต่ละตัวเลือกเพื่อรับค่าค่าในกล่องไฟล์ไฟล์แล้วส่งไปยังเซิร์ฟเวอร์พื้นหลัง แน่นอนว่ามันเป็นไปไม่ได้ (เนื่องจากปัญหานี้ฉันได้ตรวจสอบข้อมูลจำนวนมากและให้สคริปต์มากมายเช่น ASP บนอินเทอร์เน็ตฉันไม่รู้ว่าจะพูดอะไร)
กลับไปที่หัวข้อจริง ๆ แล้วมันไม่ยากที่จะอัปโหลด AJAX และมีวิธีการมากมาย ปลั๊กอิน ajaxfileupload.js สำหรับ phpletter.com ที่กล่าวถึงในบทความนี้เป็นวิธีการใช้ iframes นี่เป็นวิธีทั่วไปเมื่ออัปโหลดโดยไม่ต้องรีเฟรชหน้าโดยไม่ต้องใช้สคริปต์ JavaScript (วิธีนี้ใช้ในการเขียนบันทึกในพื้นหลัง bo-blog ของบล็อกนี้)
ปลั๊กอิน ajaxfileupload.js ก็ง่ายมาก ก่อนอื่นใช้ jQuery selector เพื่อรับค่าพา ธ ไฟล์ในกล่องอัปโหลดไฟล์จากนั้นสร้าง iframe แบบไดนามิกและสร้างกล่องไฟล์ไฟล์ใหม่ภายในให้วิธีการโพสต์เพื่อส่งไปยังพื้นหลัง ในที่สุดกลับไปที่ผลลัพธ์ไปยังแผนกต้อนรับ
2. ใช้
การใช้ปลั๊กอิน AjaxFileUpload.js นั้นง่ายมาก
โค้ด HTML แผนกต้อนรับจะคล้ายกัน:
<script type = "text/javaScript"> $ (#buttonPlod) .click (function () {$ .ajaxfileupload ({url: 'doajaxfileupload.php', // เซิร์ฟเวอร์ที่คุณจัดการกับการอัปโหลดไฟล์: imgat // ส่งคืนประเภทข้อมูล: ข้อความ, xml, json, html, scritp, jsonp ห้าความสำเร็จ: ฟังก์ชั่น (ข้อมูล) {แจ้งเตือน (data.file_infor); AjaxFileUpload (); "> อัปโหลด </button>พื้นหลัง doajaxfileupload.php สคริปต์:
<? php $ upfilepath = "../attachment/";?$ok=@move_uploaded_file($_files [immg'. เหมือนกัน ['tmp_name'like,$upfilepath); if ($ ok === false) {echo json_encode ('file_infor' => 'การอัปโหลดล้มเหลว'); } else {echo json_encode ('file_infor' => 'อัปโหลดสำเร็จ'); -สำหรับการทดสอบคุณสามารถบันทึกค่าตัวแปรที่ผ่านในลักษณะเดียวกันกับต่อไปนี้:
$ file_info = var_export ($ _ ไฟล์จริง);
$ ok = file_put_contents ("../ ไฟล์แนบ/file_info.txt", $ file_info);
ถ้า ($ OK) ออก (JSON_ENCODE ('file_infor' => 'อัปโหลดสำเร็จ'));
ออก (json_encode ('file_infor' => 'การอัปโหลดล้มเหลว'));
※ สังเกต
โปรดทราบเครื่องหมายในกล่องไฟล์รหัส HTML:
1. id = 'img' ใช้เพื่อระบุ FileElementId: 'IMG' ของปลั๊กอิน AjaxFilePilePload.js ตัวเลือก jQuery จะใช้สตริงนี้เพื่อรับค่าของกล่องข้อความ
2. name = 'img' ใช้เพื่ออ่านข้อมูลไฟล์ที่อัปโหลดผ่าน $ _files ['img'] เมื่อส่งไปยังสคริปต์พื้นหลังผ่านโพสต์ หากไม่มีค่านี้ตัวแปร $ _files จะว่างเปล่า
ดังนั้นทั้งสองค่านี้จึงขาดไม่ได้และไม่สามารถสับสนได้
3. สนับสนุนพารามิเตอร์เพิ่มเติม
บางครั้งเราจำเป็นต้องจัดการไฟล์ที่อัปโหลดตามตัวแปรบางตัวในพื้นหลัง ตัวอย่างเช่นอัปเดตไฟล์ ในเวลานี้คุณต้องผ่านพารามิเตอร์เพิ่มเติมบางอย่างไปยังขั้นตอนเดียวกัน ดังนั้นฉันแก้ไขปลั๊กอิน ajaxfileupload.js:
addotherRequestStoform: ฟังก์ชั่น (รูปแบบ, ข้อมูล) {// เพิ่มพารามิเตอร์พิเศษ var regunicelement = $ ('input type = "hidden" name = "" value = "">'); สำหรับ (คีย์ var ในข้อมูล) {name = key; value = data [key]; var cloneElement = OriginalElement.clone (); CloneElement.attr ({'name': ชื่อ, 'value': value}); $ (CloneElement) .appendto (แบบฟอร์ม); } return form;}, ajaxfileupload: ฟังก์ชั่น {// todo แนะนำการตั้งค่าทั่วโลกช่วยให้ลูกค้าสามารถแก้ไขได้สำหรับคำขอทั้งหมดไม่เพียง แต่หมดเวลา s = jQuery.extend ({}, jQuery.ajaxsettings, s); var id = วันที่ใหม่ (). getTime () ฟอร์ม var = jQuery.createuploadform (id, s.fileElementId); if (s.data) แบบฟอร์ม = jQuery.addotherRequestStoform (รูปแบบ, s.data); var io = jQuery.createuploadiframe (id, s.secureuri);ส่วนเครื่องหมายสีแดงคือสิ่งที่ฉันเพิ่ม วิธีนี้ฉันสามารถผ่านพารามิเตอร์เพิ่มเติมในส่วน HTML เบื้องหน้าผ่านรหัสด้านล่าง:
url: 'doajaxfileupload.php', // เซิร์ฟเวอร์ที่คุณจัดการไฟล์อัพโหลด
SecureUri: FALSE, // ค่า id ที่สอดคล้องกับไฟล์ในรหัสการประมวลผลหน้าเว็บ
ข้อมูล: {'ทดสอบ': 'ทดสอบ', 'ตกลง': 'ตกลง'}, // ผ่านในวัตถุและส่วนเนื้อหาสามารถป้อนค่าตัวแปรของ JavaScript
filelementId: 'img',
สคริปต์การประมวลผลพื้นหลังคือ:
array_push ($ _ ไฟล์, $ _ คำขอ); $ file_info = var_export ($ _ files, true); $ ok = file_put_contents ("../ attachment/file_info.txt", $ file_info); ถ้า ($ OK) ออก (json_encode ('file_infor' => 'การอัปโหลดล้มเหลว'));จะเห็นได้ว่าหลักการนั้นง่ายมากซึ่งคือการเพิ่มเนื้อหาวัตถุข้อมูลเพิ่มเติมลงในแบบฟอร์มภายใต้ iframe ส่งผ่านไปยังสคริปต์ PHP พื้นหลังและรับค่าเหล่านี้ด้วยตัวแปรเช่น $ _request
เนื้อหา file_info.txt เก็บไว้ในเอาต์พุตพื้นหลังมีดังนี้:
อาร์เรย์ (
'ไฟล์' =>
อาร์เรย์ (
'ชื่อ' => 'firefox-java.txt'
'type' => 'ข้อความ/ธรรมดา'
'tmp_name' => 'd: //tools//xampp//tmp//phped45.tmp'
'ข้อผิดพลาด' => 0,
'ขนาด' => 250
-
0 =>
อาร์เรย์ (
'ทดสอบ' => 'ทดสอบ',
'ตกลง' => 'ตกลง'
'phpsessid' => 'e379fd4fb2abca6e802a1302805a5535'
-
-
ajaxfileupload.js:
jQuery.extend ({createUploadiframe: function (id, uri) {// สร้าง framevar frameid = 'juploadframe' + id; if (window.activexobject) {var io = document.createelement ('<iframe id = " + frameid +' 'Boolean') {io.src = 'JavaScript: false';} อื่นถ้า (typeof uri == 'String') {io.src = uri;}} else {var io = document.createLelement ('iframe'); io.id = framidid; 'Absolute'; io.style.top = '-1000px'; io.style.left = '-1000px'; action = "method =" post "name =" ' + formId +' "id =" ' + formId +' "enctype =" multipart/form-data "> </form> '); $ (oldElement). ก่อน (newElement); $ (แบบฟอร์ม) .css ('top', '-1200px'); $ (แบบฟอร์ม) .css ('ซ้าย', '-1200px'); $ (แบบฟอร์ม) .appendto ('ร่างกาย'); แบบฟอร์มกลับ; }, addotherRequestStoform: ฟังก์ชั่น (รูปแบบ, ข้อมูล) {// เพิ่มพารามิเตอร์พิเศษ var OriginalElement = $ ('<อินพุต type = "hidden" name = "" value = "">'); สำหรับ (คีย์ var ในข้อมูล) {name = key; value = data [key]; var cloneElement = OriginalElement.clone (); CloneElement.attr ({'ชื่อ': ชื่อ, 'ค่า': ค่า}); $ (CloneElement) .appendto (แบบฟอร์ม); } แบบฟอร์มส่งคืน; }, ajaxfileupload: ฟังก์ชั่น {// todo แนะนำการตั้งค่าทั่วโลกอนุญาตให้ลูกค้าแก้ไขพวกเขาสำหรับคำขอทั้งหมดไม่เพียง แต่หมดเวลา s = jQuery.extend ({}, jQuery.ajaxsettings, s); var id = วันที่ใหม่ (). getTime () ฟอร์ม var = jQuery.createuploadform (id, s.fileElementId); if (s.data) แบบฟอร์ม = jQuery.addotherRequestStoform (รูปแบบ, s.data); var io = jQuery.createuploadiframe (id, s.secureuri); var frameid = 'juploadframe' + id; var formId = 'juploadform' + id; // ดูชุดคำขอใหม่ถ้า (s.global &&! jQuery.active ++) {jQuery.event.trigger ("ajaxstart"); } var requestDone = false; // สร้างวัตถุคำขอ var xml = {} ถ้า (s.global) jQuery.event.trigger ("ajaxsend", [xml, s]); // รอการตอบกลับกลับมา var uploadCallback = ฟังก์ชั่น (isTimeOut) {var io = document.getElementById (frameid); ลอง {ถ้า (io.contentWindow) {xml.ResponSetext = io.ContentWindow.Document.body? xml.responsexml = io.contentwindow.document.xmldocument? io.contentwindow.document.xmldocument: io.contentwindow.document; } อื่นถ้า (io.contentDocument) {xml.responsetext = io.contentDocument.document.body? io.contentDocument.document.body.innerhtml: null; xml.responsexml = io.contentdocument.document.xmldocument? io.contentDocument.document.xmldocument: io.contentDocument.Document; }} catch (e) {jQuery.handleerror (s, xml, null, e); } if (xml || istimeout == "หมดเวลา") {requestdone = true; สถานะ var; ลอง {status = istimeout! = "หมดเวลา"? "ความสำเร็จ": "ข้อผิดพลาด"; // ตรวจสอบให้แน่ใจว่าคำขอนั้นสำเร็จหรือไม่ได้รับการแก้ไข (สถานะ! = "ข้อผิดพลาด") {// ประมวลผลข้อมูล (เรียกใช้ XML ผ่าน httpData โดยไม่คำนึงถึงการโทรกลับ) var data = jQuery.uploadhttpData (XML, S.Datatype); // หากมีการระบุการโทรกลับในท้องถิ่นให้ยิงมันและส่งผ่าน Dataif (S.Success) S.Success (ข้อมูลสถานะ); // ยิงการเรียกกลับทั่วโลก (s.global) jQuery.event.trigger ("ajaxsuccess", [xml, s]; "ข้อผิดพลาด"; jQuery.HandleERROR (S, XML, สถานะ, e);} // คำขอนั้นสมบูรณ์ (s.global) jQuery.event.trigger ("ajaxcomplete", [xml, s]); // จัดการ Ajax counterif ทั่วโลก (s.global &&! -JQuery.active) jQuery.event.trigger ("ajaxstop"); // ผลการดำเนินการ (s.complete) s.complete (XML, สถานะ); jQuery (io) .unbind () settimeout (function () {ลอง {$ (io) .remove (); $ (รูปแบบ). remove ();} catch (e) {jQuery.HandleerRor (s, xml, null, e);}, 100) xml = null} {settimeout (function () {// ตรวจสอบเพื่อดูว่าคำขอยังคงเกิดขึ้น (! requestdone) uploadCallback ("หมดเวลา");}, s.timeout); } ลอง {// var io = $ ('#' + frameid); var form = $ ('#' + formId); $ (แบบฟอร์ม) .attr ('การกระทำ', s.url); $ (แบบฟอร์ม) .attr ('วิธี', 'โพสต์'); $ (แบบฟอร์ม) .attr ('เป้าหมาย', frameid); if (form.encoding) {form.encoding = 'multipart/form-data'; } else {form.enctype = 'multipart/form-data';} $ (แบบฟอร์ม) .submit (); } catch (e) {jQuery.HandleERror (s, xml, null, e); } if (window.attacheVent) {document.getElementById (frameid) .AttAcheVent ('onLoad', uploadCallback); } else {document.getElementById (frameId) .AddEventListener ('โหลด', uploadCallback, false); } return {abort: function () {}}; }, uploadhttpdata: ฟังก์ชัน (r, type) {var data =! type; data = type == "xml" || ข้อมูล ? R.Responsexml: R.ResponSetext; // ถ้าประเภทคือ "สคริปต์" ให้ประเมินในบริบทส่วนกลางถ้า (ประเภท == "สคริปต์") jQuery.globaleval (ข้อมูล); // รับวัตถุ JavaScript หากใช้ JSON if (type == "json") eval ("data =" + data); // ประเมินสคริปต์ภายใน html ถ้า (type == "html") jQuery ("<div>"). html (data) .evalscripts (); // Alert ($ ('param', data) .each (function () {Alert ($ (this) .attr ('value'));})); ส่งคืนข้อมูล -