ภาพรวม
บทความนี้จะอธิบายตัวอย่างการใช้เทคโนโลยี XML เพื่ออัปโหลดไฟล์ วิธีการนี้ไม่มีข้อจำกัดของวิธีการแบบเดิม ตัวอย่างนี้อธิบายวิธีการใช้ MSXML3.0 และวัตถุกระแสข้อมูล ADO เพื่อใช้วิธีการอัปโหลดใหม่นี้ มีประโยชน์มากมาย เช่น ไม่จำเป็นต้องมีองค์ประกอบการอัปโหลดโดยเฉพาะ
การแนะนำ
เพื่อให้ได้ฟังก์ชันการอัปโหลดในหน้าเว็บ HTML เราสามารถใช้รูปแบบต่อไปนี้ของ FORM บนไคลเอนต์:
<FORM NAME="myForm"
ACTION="TargetURL.asp"
ENCTYPE="หลายส่วน/แบบฟอร์มข้อมูล"
วิธีการ = "โพสต์">
<ประเภทอินพุต="ไฟล์" NAME="myFile">
<INPUT TYPE="ส่ง" VALUE="อัปโหลดไฟล์">
</FORM>
โซลูชันนี้มีข้อจำกัดมากมายเกี่ยวกับการใช้ทั้งไคลเอ็นต์และเซิร์ฟเวอร์ ขั้นแรก เราต้องใช้วิธี POST เนื่องจากวิธี GET ไม่สามารถจัดการข้อมูลในแบบฟอร์มดังกล่าวได้ นอกจากนี้ ไม่มีทางที่จะทริกเกอร์การดำเนินการ POST โดยไม่ใช้แบบฟอร์มได้ หลังจากส่งข้อมูลไปยังตัวจัดการแบบฟอร์มแล้ว เบราว์เซอร์จะโหลดตัวจัดการเป็นหน้าใหม่และผู้ใช้จะเห็นการเปลี่ยนแปลงหน้าที่ไม่พึงประสงค์
คุณลักษณะ ENCTYPE กำหนดวิธีการเข้ารหัส MIME สำหรับแบบฟอร์ม คุณลักษณะ ENCTYPE ของแบบฟอร์มสำหรับการอัปโหลดไฟล์ต้องใช้ "multipart/form-data" การตั้งค่าแอตทริบิวต์นี้เป็น "multipart/form-data" จะสร้างบัฟเฟอร์ POST (โครงสร้างคอมโพสิต) ที่แตกต่างจากโครงสร้างแบบเดิม วัตถุคำขอของ ASP ไม่สามารถเข้าถึงเนื้อหาแบบฟอร์มดังกล่าวได้ ดังนั้นเราจึงสามารถใช้เมธอด Request.binaryRead เพื่อเข้าถึงข้อมูลนี้ได้ แต่เราไม่สามารถทำได้โดยใช้ภาษาสคริปต์ เมธอด Request.binaryRead ส่งคืนข้อมูลประเภท VTaray (อาร์เรย์ประเภท Variant ที่มีอักขระไบต์เดียวที่ไม่ได้ลงนามเท่านั้น) แต่ภาษาสคริปต์สามารถรองรับได้เฉพาะข้อมูล Variant เท่านั้น เพื่อแก้ไขปัญหานี้ คุณสามารถใช้ได้เฉพาะคอมโพเนนต์การอัปโหลด ASP เฉพาะหรือส่วนขยาย ISAPI เช่น CPSHOST.DLL นี่เป็นข้อจำกัดในการออกแบบ
แผนการอัปโหลดใหม่
ต้องทำตามขั้นตอนต่อไปนี้
ลูกค้า:
ใช้ MSXML 3.0 เพื่อสร้างเอกสาร XML สร้างโหนด XML สำหรับเนื้อหา
ไบนารี ด้านข้าง:
อ่านเอกสาร XML จากอ็อบเจ็กต์ Request อ่านข้อมูลในโหนดไบนารี่ และจัดเก็บไว้ในไฟล์บนเซิร์ฟเวอร์ แน่นอนว่าเราสามารถจัดเก็บไว้ในเขตข้อมูล BLOB ในฐานข้อมูลได้
ก่อนที่จะอธิบายโค้ดนี้ เราสามารถคิดเกี่ยวกับวิธีแก้ปัญหานี้ได้ก่อน
ความคิดเกี่ยวกับ XML
รูปแบบ XML รองรับข้อมูลหลายประเภท เช่น ตัวเลข ทศนิยม อักขระ ฯลฯ ผู้เขียนหลายคนกำหนด XML เป็นรูปแบบ ASCII แต่เราไม่สามารถเพิกเฉยได้ว่าเทคโนโลยี XML ยังสามารถใช้ประเภทข้อมูล "bin.base64" เพื่ออธิบายข้อมูลไบนารี่ได้ คุณลักษณะนี้ได้รับการสนับสนุนอย่างสมบูรณ์ในตัวแยกวิเคราะห์ MS XML3.0 แต่ในปัจจุบันจำเป็นต้องมีการตั้งค่าพิเศษบางอย่าง ออบเจ็กต์นี้มีคุณสมบัติบางอย่างที่อนุญาตให้ควบคุมข้อมูลไบนารีได้อย่างสมบูรณ์:
obj_node.dataType - คุณสมบัติอ่าน-เขียนนี้กำหนดประเภทข้อมูลของโหนดเฉพาะ ตัวแยกวิเคราะห์ MSXML รองรับประเภทข้อมูลมากขึ้น (ดู MSDN: http://msdn.microsoft.com/library/psdk/xmlsdk/xmls3z1v.htm )
สำหรับข้อมูลไบนารีเราสามารถใช้ประเภท "bin.base64"
obj_node.nodeTypedValue - คุณสมบัติการอ่าน-เขียนนี้มีข้อมูลที่แสดงถึงโหนดที่ระบุในแง่ของประเภทที่ระบุ
เราสามารถสร้างเอกสาร XML ที่มีโหนดประเภท bin.base64 หลายโหนดซึ่งมีไฟล์ที่อัปโหลด คุณลักษณะนี้ช่วยให้คุณสามารถอัปโหลดหลายไฟล์พร้อมกันโดยใช้ POST เดียว
เราสามารถใช้วัตถุ XMLHttpRequest และวิธีการ POST เพื่อส่งเอกสาร XML ไปยังเว็บเซิร์ฟเวอร์ ออบเจ็กต์นี้ให้การสนับสนุนโปรโตคอลฝั่งไคลเอ็นต์แก่เซิร์ฟเวอร์ HTTP ทำให้สามารถส่งและรับออบเจ็กต์ MS XMLDOM บนเว็บเซิร์ฟเวอร์ได้ XMLHttpRequest เป็นวัตถุ COM ในตัวใน Internet Explorer 5 (ไม่จำเป็นต้องติดตั้งแบบกำหนดเอง) และไม่จำเป็นต้องแปลงเพจหลังจากส่ง
เมื่อคิดถึงวัตถุ ADO Stream
เราสามารถสร้างเอกสาร XML ที่มีโหนดไบนารีตั้งแต่หนึ่งโหนดขึ้นไปในฝั่งไคลเอ็นต์ เรายังต้องเติมโหนดด้วยเนื้อหาไฟล์ น่าเสียดายที่ภาษาสคริปต์ไม่สามารถเข้าถึงระบบไฟล์ในเครื่องได้และออบเจ็กต์ Scripting.FileSystem (ออบเจ็กต์ในตัวของระบบ Win32) ยังไม่สามารถเข้าถึงไฟล์ไบนารี่ได้ นี่เป็นข้อจำกัดในการออกแบบ ดังนั้นเราจึงจำเป็นต้องค้นหาวัตถุ COM อื่นที่สามารถเข้าถึงไบนารีในเครื่องได้
วัตถุกระแสข้อมูล ADO (ส่วนประกอบใน MDAC 2.5) ให้วิธีการอ่าน เขียน และจัดการข้อมูลกระแสข้อมูลไบนารี เนื้อหาของสตรีมไบต์อาจเป็นข้อความหรือข้อมูลไบนารี และไม่มีขีดจำกัดความจุ ใน ADO 2.5 การแนะนำวัตถุ Stream ของ Microsoft ไม่ได้อยู่ในเลเยอร์ใดๆ ของโครงสร้างวัตถุ ADO ดังนั้นเราจึงสามารถใช้วัตถุได้โดยไม่ต้องรวมกลุ่ม
ในบทความนี้ สตรีมวัตถุถูกใช้ในการเข้าถึงเนื้อหาไฟล์ และจากนั้น เนื้อหาจะถูกเก็บไว้ในโหนด XML
บนฝั่งไคลเอ็นต์
ใช้ออบเจ็กต์ Stream และ MSXML เพื่อดำเนินการอัปโหลดไฟล์ให้เสร็จสมบูรณ์
<HTML>
<HEAD><TITLE>ส่งไฟล์</TITLE></HEAD>
<ร่างกาย>
<INPUT id=btn_send name="btn_send" type=button value="FILE ส่ง">
<DIV id=div_message>พร้อม</DIV>
</ร่างกาย>
</HTML>
<SCRIPT LANGUAGE=javascript>
// ฟังก์ชั่นอัพโหลด
ฟังก์ชั่น btn_send.onclick()
-
//สร้างวัตถุ ADO-stream
var ado_stream = new ActiveXObject("ADODB.Stream");
// สร้างเอกสาร XML ที่มีข้อมูลส่วนหัวเริ่มต้นและโหนดรูท
var xml_dom = ActiveXObject ใหม่ ("MSXML2.DOMDocument");
xml_dom.loadXML('<?xml version="1.0" ?> <root/>');
//ระบุประเภทข้อมูล
xml_dom.documentElement.setAttribute("xmlns:dt", "urn:schemas-microsoft-com:datatypes");
// สร้างโหนดใหม่และตั้งค่าเป็นโหนดข้อมูลไบนารี
var l_node1 = xml_dom.createElement("file1");
l_node1.dataType = "bin.base64";
//เปิดวัตถุ Stream และอ่านไฟล์ต้นฉบับ
ado_stream.Type = 1; // 1=adTypeBinary
ado_stream.Open();
ado_stream.LoadFromFile("c:\tmp\myfile.doc");
//บันทึกเนื้อหาไฟล์ลงในโหนด XML
l_node1.nodeTypedValue = ado_stream.Read(-1); // -1=adReadAll
ado_stream.ปิด();
xml_dom.documentElement.appendChild(l_node1);
// คุณสามารถสร้างไบนารี่หลายโหนดและอัปโหลดหลายไฟล์ในคราวเดียว
// ส่งเอกสาร XML ไปยังเว็บเซิร์ฟเวอร์
var xmlhttp = ใหม่ ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.open("POST","./file_recieve.asp",false);
xmlhttp.send(xml_dom);
// แสดงข้อมูลที่ส่งคืนโดยเซิร์ฟเวอร์
div_message.innerHTML = xmlhttp.ResponseText;
-
</สคริปต์>
บนฝั่งเซิร์ฟเวอร์
ใช้ออบเจ็กต์เดียวกันเพื่อให้ฟังก์ชันการประมวลผลการอัปโหลดฝั่งเซิร์ฟเวอร์
<%@ LANGUAGE=VBScript%>
<% ตัวเลือกที่ชัดเจน
Response.Expires = 0
' กำหนดตัวแปรและอ็อบเจ็กต์
ado_stream สลัว
dimxml_dom
dim xml_file1
'สร้างวัตถุสตรีม
ตั้ง ado_stream = Server.CreateObject("ADODB.Stream")
' สร้างวัตถุ XMLDOM จากวัตถุคำขอ
ตั้งค่า xml_dom = Server.CreateObject("MSXML2.DOMDocument")
xml_dom.load(คำขอ)
'อ่านโหนดที่มีข้อมูลไบนารี
set xml_file1 = xml_dom.selectSingleNode("root/file1")
'เปิดวัตถุ Stream และเก็บข้อมูลไว้ในนั้น
ado_stream.Type = 1 ' 1=adTypeBinary
ado_stream.open
ado_stream.เขียน xml_file1.nodeTypedValue
'บันทึกไฟล์
ado_stream.SaveToFile "c:tmpupload1.doc",2 ' 2=adSaveCreateOverWrite
ado_stream.close
' ทำลายวัตถุ
ตั้งค่า ado_stream = ไม่มีอะไรเลย
set xml_dom = ไม่มีเลย
'ส่งข้อมูลกลับไปยังเบราว์เซอร์
ตอบกลับเขียนว่า "อัปโหลดสำเร็จ!"
%>
คุณยังสามารถใช้วัตถุ Stream เพื่อใส่ข้อมูลลงในเขตข้อมูล BLOB ของฐานข้อมูลได้
ประโยชน์ของการใช้วิธีนี้คือ
ไม่ทำให้เกิดการแปลงหน้า
ไม่จำเป็นต้องมีส่วนประกอบพิเศษ
สามารถอัพโหลดหลายไฟล์พร้อมกันได้
โปรแกรมนี้เขียนด้วยสคริปต์ล้วนๆ และสามารถแทรกลงในโค้ดอื่นได้อย่างง่ายดายโดยไม่ต้องอาศัยความร่วมมือจากอ็อบเจ็กต์ HTML ใดๆ ตรรกะนี้สามารถนำไปใช้ในภาษาใดก็ได้ที่รองรับมาตรฐาน COM
ข้อควรพิจารณาด้านความปลอดภัยของระบบ:
วิธีการนี้สามารถใช้ได้กับเครือข่ายภายในเท่านั้น เนื่องจากต้องตั้งค่าระดับความปลอดภัยของ IE5 เป็น "ต่ำ" จำเป็น:
อนุญาตสคริปต์และออบเจ็กต์ ActiveX การตั้งค่านี้ทำให้เบราว์เซอร์สามารถรันคำสั่ง JScript เช่น "myobj = new activexobject(...)";
ต้องอนุญาตให้เข้าถึงแหล่งข้อมูลข้ามโดเมน การตั้งค่านี้อนุญาตให้ใช้วัตถุกระแสข้อมูลบนฝั่งไคลเอ็นต์ ต้องติดตั้ง MS XML DOM 3.0 และ MDAC 2.5 บนทั้งเซิร์ฟเวอร์และไคลเอนต์