Overview
This article explains an example of using XML technology to upload files. This method does not have the limitations of traditional methods. This example describes how to use MSXML3.0 and the ADO Stream object to implement this new upload method. There are many benefits, such as no need for a dedicated upload component.
introduction
In order to obtain the upload function in HTML web pages, we can use the following format of FORM on the client:
<FORM NAME="myForm"
ACTION="TargetURL.asp"
ENCTYPE="multipart/form-data"
METHOD="post">
<INPUT TYPE="file" NAME="myFile">
<INPUT TYPE="submit" VALUE="Upload File">
</FORM>
This solution has many limitations on the use of both the client and the server. First, we have to use the POST method because the GET method cannot handle such form data. Also, there is no way to trigger a POST action without using a form. After sending the data to the form handler, the browser will load the handler as a new page, and the user will see an unpleasant page transition.
The ENCTYPE attribute defines the MIME encoding method for the form. The ENCTYPE attribute of the form for uploading files must use "multipart/form-data". Setting this attribute to "multipart/form-data" creates a POST buffer (composite structure) that is different from the traditional structure. ASP's Request object cannot access such form content. So, we can use the Request.binaryRead method to access this data, but we can't do it using a scripting language. The Request.binaryRead method returns a VTaray type data (a Variant type array containing only unsigned one-byte characters). But scripting languages can only handle Variant data. In order to solve this problem, you can only use dedicated ASP upload components, or ISAPI extensions, such as CPSHOST.DLL. This is a design limitation.
The new upload plan
needs to follow the following steps.
Client:
Use MSXML 3.0 to create an XML document. Create an XML node for binary content. Use the ADO Stream object to put the uploaded file data into the node. Use the XMLHTTP object to send the XML document to the Web server
. Server-side:
Read the XML document from the Request object, read the data in the binary node and store it in a file on the server. Of course, we can also store it in a BLOB field in the database.
Before explaining this code, we can give some thought to this solution.
Thoughts on XML
The XML format supports many data types, such as numeric, float, character, etc. Many authors define XML as ASCII format, but we cannot ignore that XML technology can also use the "bin.base64" data type to describe binary information. This feature is fully supported in the MS XML3.0 parser, but currently requires some special settings. This object provides some properties that allow full control over binary data:
obj_node.dataType - This read-write property defines the data type of a specific node. The MSXML parser supports more data types (see MSDN: http://msdn.microsoft.com/library/psdk/xmlsdk/xmls3z1v.htm )
For binary data we can use the "bin.base64" type.
obj_node.nodeTypedValue - This read-write property contains data representing the specified node in terms of the specified type.
We can create an XML document containing multiple bin.base64 type nodes, which contain uploaded files. This feature allows you to upload multiple files at once using one POST.
We can use the XMLHttpRequest object and the POST method to send an XML document to the Web server. This object provides client-side protocol support to the HTTP server, allowing MS XMLDOM objects to be sent and received on the web server. XMLHttpRequest is a built-in COM object in Internet Explorer 5 (no custom installation required), and there is no need to convert the page after sending.
Thinking about the ADO Stream object
We can create an XML document containing one or more binary nodes on the client side. We also have to populate the node with the file contents. Unfortunately, scripting languages cannot access the local file system, and the Scripting.FileSystem object (a built-in object of the Win32 system) has not been able to access binary files so far. This is a design limitation. So we need to find another COM object that can provide access to local binaries.
The ADO Stream object (component in MDAC 2.5) provides the means to read, write, and manage binary stream data. The content of the byte stream can be text or binary data, and there is no capacity limit. In ADO 2.5, Microsoft's introduction of the Stream object does not belong to any layer of the ADO object structure, so we can use the object without bundling.
In this article, the Stream object is used to access the file content, and then the content is stored in the XML node.
on the client side
uses Stream and MSXML objects to complete the file upload action.
<HTML>
<HEAD><TITLE>File Send</TITLE></HEAD>
<BODY>
<INPUT id=btn_send name="btn_send" type=button value="FILE SEND">
<DIV id=div_message>Ready</DIV>
</BODY>
</HTML>
<SCRIPT LANGUAGE=javascript>
// Upload function
function btn_send.onclick()
{
//Create ADO-stream object
var ado_stream = new ActiveXObject("ADODB.Stream");
// Create an XML document containing default header information and root node
var xml_dom = new ActiveXObject("MSXML2.DOMDocument");
xml_dom.loadXML('<?xml version="1.0" ?> <root/>');
//Specify data type
xml_dom.documentElement.setAttribute("xmlns:dt", "urn:schemas-microsoft-com:datatypes");
// Create a new node and set it as a binary data node
var l_node1 = xml_dom.createElement("file1");
l_node1.dataType = "bin.base64";
//Open the Stream object and read the source file
ado_stream.Type = 1; // 1=adTypeBinary
ado_stream.Open();
ado_stream.LoadFromFile("c:\tmp\myfile.doc");
//Save file content into XML node
l_node1.nodeTypedValue = ado_stream.Read(-1); // -1=adReadAll
ado_stream.Close();
xml_dom.documentElement.appendChild(l_node1);
// You can create multiple binary nodes and upload multiple files at one time
// Send the XML document to the Web server
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.open("POST","./file_recieve.asp",false);
xmlhttp.send(xml_dom);
// Display the information returned by the server
div_message.innerHTML = xmlhttp.ResponseText;
}
</SCRIPT>
on the server side
uses the same object to provide server-side upload processing functionality.
<%@ LANGUAGE=VBScript%>
<% Option Explicit
Response.Expires = 0
' Define variables and objects.
dim ado_stream
dimxml_dom
dim xml_file1
'Create Stream object
set ado_stream = Server.CreateObject("ADODB.Stream")
' Create an XMLDOM object from the Request object
set xml_dom = Server.CreateObject("MSXML2.DOMDocument")
xml_dom.load(request)
'Read nodes containing binary data
set xml_file1 = xml_dom.selectSingleNode("root/file1")
'Open the Stream object and store the data in it
ado_stream.Type = 1 ' 1=adTypeBinary
ado_stream.open
ado_stream.Write xml_file1.nodeTypedValue
'File save
ado_stream.SaveToFile "c:tmpupload1.doc",2 ' 2=adSaveCreateOverWrite
ado_stream.close
' Destroy object
set ado_stream = Nothing
set xml_dom = Nothing
'Return information to the browser
Response.Write "Upload successful!"
%>
You can also use the Stream object to put data into the BLOB field of the database.
The benefit of using this method is that
it does not cause page conversions.
No special components are required.
Multiple files can be uploaded at the same time.
This program is written in pure script and can be easily inserted into other codes without the cooperation of any HTML objects. This logic can also be implemented in any language that supports the COM standard.
System security considerations:
This method can only be used on internal networks because it requires the security level of IE5 to be set to "low". Required:
Allow scripts and ActiveX objects. This setting allows the browser to execute JScript statements like "myobj = new activexobject(...)";
Cross-domain access to the data source must be allowed. This setting allows the use of Stream objects on the client side. MS XML DOM 3.0 and MDAC 2.5 must also be installed on both the server and client.