[ASP]利用 xmlhttp 分块上传文件
编写思路:把本地文件在客户端通过base64编码以后发送目的地.
8 Y" e" J# Q; ~- w" a3 o测试过程中,上传文件过大,导致超时不成功.% e8 t, w4 @/ ]" m* d
后来经过改善.把编码分段发送.测试20M成功* w# @6 V" m# E" O/ w
+ k3 b0 t5 t' q/ J' @' V
编写目的:在传统的解决方案里面,一次一次选取上传可以.但是在碰到把数据库里文件路径读出来,并把这些文件上传到一个地方的时候就比较麻烦.
& Z0 _% z4 n# ?4 ~; z! m# ^如果得到路径一个一个去找到用ftp当然也是可以的,但每次找这些文件我看都会比较费时。这里编写这个主要就是为了通过数据库里的文件路径取得文件.把文件一次批量上传到一个地方.
, W1 o4 @' V6 d$ p4 G3 U其主要目的还是为了锻炼一下自己.
+ n i2 }+ d9 w* W M; Z3 Z8 n* R) O* Q7 y& T* s
解决过程:起初试着用模拟键盘输入强行赋值给file控件用传统的方法上传。可是老碰到空值的情况,以至有很多文件没有发送出去。查阅一些资料,现在是把所有路径通过数据库取到然后写到一个js里。然后在前台用js读取这些路径,通过xmlhttp来发送文件。5 i4 a# f' j( G! x! C
因为ie不太喜欢xmlHttp.总认为他有恶意行为.所以老谈出提示警告.所以操作的时候不能使用web路径.只能用物理路径去访问它.9 }: J, Z3 W. g% d- l
然后服务端有一文件来接收这些编码,并对其进行解码.所以我称之为"c/s". ^_^" J0 i0 J! Q6 g6 r. }( |
) x5 H& ~4 D, H目前很多代码还在完善中.
2 f8 ^2 [/ N- k/ D- O' t4 U! I9 B( s简单介绍一下:
0 U0 \3 N$ V. [* x+ H% c F
, f4 Y) j% ^. j' t; C! {aryFiles.push("c:\\aaa.zip") ;3 U$ a( _, Y2 y9 _3 r# m* {
aryFiles.push("c:\\bbb.exe") ;
6 F1 A" Y F. ]" |2 y( ~' Q2 o这里为文件路径和文件.可为多个
3 M3 N4 ^' O i( j) Y以后这个路径也可以通过file控件在客户端取到
5 v# i1 E5 z; ]7 w6 s: Q+ L% b7 ?. j Q6 p8 D
http:// www.xxx.com/xxx/xxx.asp
9 A' J7 ?( L, s/ u8 @4 c这个是目的地,可以改为自己想要的地址.( J7 T9 l6 `$ _7 `+ U4 r
- p( p7 ~9 {7 F! z7 C/ R- ^% |5 b/ a' hado_stream.LoadFromFile(server.mappath(".") "/" str_filename) : V7 b$ @# Z9 V; f0 p
server.mappath(".") "/" str_filename 这里是读取文件.
+ z; w2 @" ? ^# N/ j( x' bserver.mappath(".") "/" 路径和存放路径一致- B8 c+ @, w* e
# A$ x: A0 I% h
ado_stream.SaveToFile server.mappath(".") "/" str_filename,2
& G. Z1 c0 B6 A/ _server.mappath(".") "/" 这个为存放文件的路径. str_filename 为文件名7 H; I, Z- R; \( j6 j
0 g1 c6 X( `, ]9 m
这里读取和存放都是放在程序所放目录中.大家测试的时候也可以保持这样即可& |! ]' G9 G+ M
( B3 w X6 ?4 ?% `/ q% e, b( ]$ J/ H
把第一段代码放到本地(eg:c:\upload.htm) Z2 w; B: r* A5 z
+ y' _$ h1 }; _6 d# R把第二段代码放到服务器上,可以是本地服务器,可以是公网服务器.和上面的目的地保持一致
# g# X' n ?2 R8 i& @- s5 ?(eg:http://www.xxx.com/upload.asp or http:// localhost/www/upload.asp)
z% b* Z3 A6 u4 j! h* d
4 k4 n3 ?# z$ q, ~/ W; Z/ m4 p3 q% @# x& M; U/ t* O# e
操作:找到第一段代码保存的地方。执行即可(eg:打开c盘执行upload.htm)
! B) v2 [# o3 x; r
2 z' Y8 Q2 o) H- j5 H& u目前程序还在调试过程中,希望大家提出宝贵意见
* S* [, i3 b0 Q+ ]
/ e' N* X- d6 _9 ^客户端代码html
2 O* V+ o' x/ ^2 B3 v- }" a1 Z4 i' @1 g6 L
head5 m5 T7 o3 M& Z* p4 G
+ [2 D: `6 K: h6 `
/head2 ?9 X4 m$ f, O6 y3 G5 @' w2 W
( \' `6 c9 ?+ f W3 ~/ K* \body input type=button
% R' ^! q4 k! @! E, |. H
+ V+ A2 U& A1 ~7 P' ^4 l0 xvalue="发送" / input type=button value="中断" / div id="ddd"% I: ~# A: R$ `7 e0 O6 Z
0 X* R3 C: s$ |" `0 ?width=300px/div br/br DIV+ }0 x4 V3 b5 y$ |5 F, K5 M
) D8 _. t6 h- f" T7 N0 z! i
id=div_message/DIV" I% d O! C5 H8 O: J
9 z) V- |% e. a2 c4 k' a; N
/body
! k+ x [! ?2 {4 w1 v6 R- J% f1 j+ _8 h0 v* _$ @
script language=VBScript Function bytes2BSTR(vIn) strReturn =7 V2 K) y8 W* a, S2 e5 c9 x1 Q: G: k
& g/ B- k2 r' X9 U
"" For i = 1 To LenB(vIn) ThisCharCode = AscB(MidB(vIn,i,1)) If/ d1 Q5 [3 a. V) W
, k/ ~/ d$ \9 ?1 H2 B {& jThisCharCode H80 Then strReturn = strReturn
" Q1 W+ ?# B) g' ?
, \1 F+ P Q' }7 g3 Y1 h$ ], C7 DChr(ThisCharCode) Else NextCharCode = AscB(MidB(vIn,i 1,1)) strReturn =
9 n2 Q _3 M/ ~$ \/ J _2 ^ n/ A% L' P9 d1 b. q
strReturn Chr(CLng(ThisCharCode) * H100
' W& j4 ?7 D8 m! w ]: k
3 D' \ ^/ V) P/ PCInt(NextCharCode)) i = i 1 End If Next bytes2BSTR = strReturn End
" w2 o) ]/ j5 j: q
5 G- {# t; x, r9 I( W/ U; I, V' qFunction8 g: q2 G( C7 Q. F9 k* o! j
( c: b+ X$ V _5 m) A
/script) t3 V) w& |. ?4 s" r
" I2 P6 W' V+ H' v% p
script language=javascript var xmlhttp ; var ado_stream ; var) g+ L- A: ^5 h+ A4 s4 q1 ~ d
0 a( D( W& w2 H2 A6 b5 R
mFileName, mPartStart, mPartID, mPartEnd ; var SendCount ; var
, l3 `/ Q; E8 ~8 p5 i
9 b" w8 r4 s8 J1 @- eBlockSize ; var Breaked ; var aryFiles ; BlockSize = 1024*100
9 j, Y# D4 a; t" _9 S. b* i0 Y$ r/ Q, [" u
;//每次发送字节数 Breaked = false ; aryFiles = new Array() ; // 开始发送文件3 k3 v& Y- o4 j: P
2 W8 D/ h; V/ g% e& G& E
function BeginSendFiles() { initAryFiles() ; SendFile(aryFiles.pop()) ;: R" f5 ~* w6 |* ?
|) {2 X# D% e( E/ K
} // 构造待发送文件的数组 function initAryFiles() { aryFiles.push("c:\\aaa.zip")9 p* J5 f A* W
8 K5 o% c- Y. N
; aryFiles.push("c:\\bbb.exe") ; //c:\\aaa.zip c:\\bbb.exe本地文件" Z+ w! v( l" J& M; z
- [( ]1 q3 X, ?
aryFiles.reverse() ;//文件名 } function SendFile(vFullPath) { // 空文件则不执行上传! p/ T- ]. y: T; ?
9 u/ H# R3 B3 t8 [
if (!vFullPath) { return ; } Breaked = false ; div_message.innerHTML =4 T; v9 d$ I7 j2 E* z" g
6 l4 C4 B8 U9 T"" ; ado_stream = new ActiveXObject("ADODB.Stream"); // 读取文件的流7 D2 q# ^! R; P
/ [ K' b: a4 l6 a$ v& bado_stream.Type = 1; ado_stream.Open();$ D% n( f: [: I; k# Y" O0 E0 R+ R0 `
6 B: z& q7 W/ {+ ~& I1 j. ~: gado_stream.LoadFromFile(vFullPath); // 读取文件 ado_stream.position = 0 ;
w* J# N3 i3 L! B' H0 O
7 ?6 j4 k* b. X, G0 OSendCount = Math.ceil(ado_stream.size/BlockSize) ; // 如果有余数则多发送一次 //1 S5 I# A2 x7 s0 R& n+ I/ B
+ e7 P& y" e+ `5 I6 Q' Galert(SendCount) ; var reg = /\b\w .\w $/gi mFileName =3 v" v8 s0 i: ?4 F
: C1 y# O& h2 O* C1 d+ ]/ C
reg.exec(vFullPath) ; mPartStart = true ; mPartID = 1 ; mPartEnd =
4 n) D) ?* D( S5 \; c4 W; `$ s4 S
- O/ m4 q4 v, Tfalse ; SendData() ; } function SendData() { if (SendCount 0) {
/ w4 [ N$ Y3 X! a- n
) K2 f6 Q- Q( ~* E! k7 T$ [var dom = new ActiveXObject("msxml2.DOMDocument"); // 发送的xml文件
3 }0 U* J& I+ C* z8 i( M$ {. [4 ?4 h+ M2 x" Q
dom.async = false; dom.resolveExternals = false; // 构造xml文件头 var node =% c$ ~' Z$ A. h: V
( G% x* S' f. \; X& I+ v2 q
dom.createProcessingInstruction("xml","version='1.0'");
$ u, }0 z$ ?& n9 T8 O9 x ~9 r0 C B4 [5 g; u5 v6 T2 m
dom.appendChild(node) ; node = null ; // 构造root节点 var root =
# O/ z' A- i1 \ \5 u
6 Y! R3 }7 g/ H" Gdom.createElement("root"); dom.appendChild(root) ;" {. H% K' Z+ P9 H
5 @) U( ?: G, Q, U5 A' q* z
dom.documentElement.setAttribute("xmlns:dt", Z4 U6 a! z5 r7 T
6 p9 {' q0 ?3 p' T
"urn:schemas-microsoft-com:datatypes"); // 构造保存二进制数据的节点updata node =
4 b9 z6 m" M+ R6 y/ Z2 y. n/ ^; \0 p
' _( e( n$ {: F" m( k( vdom.createElement("upData") ; node.dataType = "bin.base64" ; //4 ~! p5 S* p: `6 h8 d
8 j1 i ]+ T- ?; P* Kbin。base64编码 var att = dom.createAttribute("FileName") ; // 文件名属性
1 o# H! K$ l! h3 c5 R( g1 C) ~! y# S" w2 {, Q
att.value = mFileName ; node.setAttributeNode(att) ; att = null ; var, i/ S$ f0 U5 w; {! j$ D5 Z
1 h+ ^( q5 N+ B0 b; G2 y9 _$ zatt = dom.createAttribute("PartStart") ; // 分段开始标记 att.value =: [/ _4 `) P: K1 e3 [: n3 B) x
; S! y4 \* H# x, emPartStart ; node.setAttributeNode(att) ; att = null ; var att =
/ w2 `2 z5 X- E0 R7 p" C* }$ z$ f, V. s. @+ ?
dom.createAttribute("PartID") ; // 分段序号 att.value = mPartID ;
3 v4 `, g- B) o/ G
8 w- x: d0 v3 h7 y5 J$ I/ q2 fnode.setAttributeNode(att) ; att = null ; var att =
" j9 ?7 B: M6 G/ j. a% e+ Y$ v+ B* D4 W! q! ~
dom.createAttribute("PartEnd") ; // 分段结束标记 att.value = mPartEnd ;1 E9 A; x" ], n9 a6 ~" a
0 Z/ ^( s5 A: |/ P
node.setAttributeNode(att) ; att = null ; root.appendChild(node) ;) ?0 U6 E; w) G+ K( Y1 i0 @
' `3 N' _) h: Q
node.nodeTypedValue = ado_stream.Read(BlockSize); // 节点数据从stream读取,固定长度: E2 |# V2 l/ p9 N' H: m; C
5 E. w" r( q% u) @
node = null ; SendCount -= 1 ; xmlhttp = new
7 W$ s2 H a! H/ h+ _( M* z7 R' w7 |3 `/ }# F. d7 Z
ActiveXObject("Microsoft.XMLHTTP");# U: [ q( N F
9 O* e/ {) b( C0 L; x4 d
xmlhttp.open("POST","http://www.xxx.com/xxx/xxx.asp", false);
6 M7 M% c: a# e) Y8 ~
p6 Q) M" m5 w* z0 t/ C, ?0 N2 G//http://www.xxx.com/xxx/xxx.asp 为web路径上的文件 xmlhttp.onreadystatechange=
0 O- \9 c1 Q: `% S& v0 B' A. a. C& P* V0 n! L# U
CallBack ; xmlhttp.send(dom); mPartStart = false ; xmlhttp = null ; }$ m% s: r( S6 i* k" ]# |
& U! X4 s+ h& s' Q7 x" eelse { ado_stream.Close(); ado_stream = null ; } } function CallBack()9 X7 Z2 \, K& R. O6 ?; X7 i9 h7 T
& H* `! Z; Y& |& S{ // 上传成功 if(xmlhttp.readystate == 4) { // 检查是否中断上传 if(Breaked) {
' N: @" a, `8 I6 h8 [
3 E2 @$ ~% q* \8 o( a, Lreturn ; } if (SendCount 0) { mPartID = 1 ; //0 _8 @9 J9 x H5 q% N
( ?6 I# v' ]5 w% ~+ X) X9 U
div_message.innerHTML = ("br" xmlhttp.ResponseText) ; var p5 @. X( ?) H5 [" J0 ?& ]) A
1 k& C9 E' j8 n: a2 b/ c= Math.floor((mPartID/(Math.ceil(ado_stream.size/BlockSize) 1)) *' X! [8 }. y6 x* ?* o
6 G6 Z b; H3 K: _& ?6 S0 k: _
100) ; // 计算进度百分比 ShowBar(p) ; var t = setTimeout("SendData();", 1) ; }: S% H2 L, G1 ^" [
8 t- C8 Y4 b+ x$ q' Q/ d
else { // 传送完文件 //div_message.innerHTML = mFileName
% H; F7 t: m, H; X/ S8 A( f5 t2 M4 D" n. X
"传送完毕!br" ; // 继续传下一文件 ShowBar(0) ; var cFile = aryFiles.pop()
( I) B$ b0 s( Z/ a6 y# f( t5 g
; SendFile(cFile) ; } } } function ShowBar(per) { // 进度条 ddd.innerHTML
# |* B& |5 F6 k& p+ O
( a; F0 W& k% d% j4 g= "table width='200' border=0 cellpadding='0' cellspacing='0'
/ j) t4 y2 ~# ]; e, G$ q8 J: z/ ~% I5 Z8 f9 ]7 r
trtd bgcolor='#6699FF'input type=button style='
$ G) J C4 h; X4 E' |
- P7 e8 v. v0 W; Iwidth:" per "% ; border:0px; background:#005599; color:#FFFFFF'3 z6 ?- o% Z t% D% s
h2 V" S9 [- N( n3 O3 S. wvalue=" per "% /td/tr/table" ; }, q2 e3 N0 ]- D1 C2 }1 H. Y
. H/ {6 h2 ]7 R
/script
% p2 T8 N2 s4 ?8 V1 V* p* A
; x6 W4 ]- r# s$ z/html [Ctrl A 全部选择 提示:你可先修改部分代码,再按运行]
! @% y# i3 \0 V6 k" c8 ~$ c+ n( z
+ m% s4 r1 o! H/ \! r+ _: v! F
6 W8 k" a6 w6 f8 _/ @# ^服务端代码%@ LANGUAGE=VBScript% ' t9 p' A+ S$ }' ^8 P. G
! U, S% E( m- F% Option Explicit
( v. L7 x. C5 h2 t5 f2 Z+ ~4 f# N, f2 U! e! r1 V
Response.Expires = 0
/ Q! s3 m! a! m- l4 _/ y ~4 \ R! h
; m- X* b5 |' y% i
: c# t% _" |4 ]0 ~$ ~
6 m4 A% l% x6 S' q3 |3 s' 定义变量和对象。 4 l% H H: m2 d! a
' G9 H; M1 A9 y3 L; L
dim ado_stream # l' C7 o9 r8 [5 E U1 ~* P% x
# ]* w& E9 e! w. q( O# f( Kdim xml_dom ! d% X( Q. I5 G2 @. b
- E0 g6 Z4 y x+ {/ v
dim xml_data
/ @/ q3 ?: h8 y# _8 B' {, _3 T9 N5 _9 s8 {* S
dim str_filename. ?, L/ l5 M( D9 Q$ D
7 J% I: { \) C* B$ k2 N" @8 K0 a& Ddim bol_PartStart
6 p- ~% }$ l& x9 @$ L1 E' v2 k# D4 ^( r
dim int_PartID6 z# a0 U% r/ ^1 {6 j
3 F* j4 Y) @8 Q5 t t: I/ {dim bol_PartEnd 5 X! Q9 M$ g* n c
1 D# d7 E! [" ~
# @$ Y) `7 H3 ^2 t ?4 Y( ~% k1 y/ J. z: f3 G- G0 v& |1 n2 e/ g
' 创建 Stream 对象
: v3 O- ]' ?4 p2 x# _' Q4 @
. \8 L5 g, v6 e0 ? _set ado_stream = Server.CreateObject("ADODB.Stream")
6 M2 W) Z& P/ D$ G8 h% c0 ]+ }$ H5 V# x
' 从Request对象创建 XMLDOM对象 , J, L0 w2 p5 N
4 c- Z( `! d2 ?% Zset xml_dom = Server.CreateObject("MSXML2.DOMDocument") + z- @( w5 V! h: s! P
, E% u$ p D, G# Y& c# oxml_dom.load(request)
( z) o; T6 b+ M5 h1 \) I# W( C7 d L- p6 n- h/ h
' 读出包含二进制数据的节点
7 Q% W' m: Q- M# E: a9 g- W* o5 I) ~# O$ ?3 m' p1 C
set xml_data = xml_dom.selectSingleNode("root/upData")
+ N1 t5 B7 {+ {- e
8 C, [2 P/ O) k2 `; E/ t) G) lstr_filename = xml_data.getAttribute("FileName")
5 {, _- z! w' C! s9 Z q" k
Y: y) z4 S4 P" h4 X3 fbol_PartStart = CBool(xml_data.getAttribute("PartStart"))
; e$ u) A% r& ~6 p: H! U
) r3 T( Z: _& Wint_PartID = CInt(xml_data.getAttribute("PartID")), ^9 ^/ \ v; N1 {, l5 D3 g
+ c' x$ a/ v" ^) o8 P+ ~bol_PartEnd = CBool(xml_data.getAttribute("PartEnd"))* N7 d4 c6 w, r2 L
/ c* _$ `# \/ w/ q" v( V7 E/ M% @6 N- f# X, V* k
9 s% E8 l. J* m$ U% A0 x' J
' 打开Stream对象,把数据存入其中
6 ^* t) t# k8 O0 y9 ?7 r9 [; b% i; @* u1 v4 F& |( _
ado_stream.Type = 1 ' 1=adTypeBinary . K8 g7 ~* s! d2 O4 O
% v9 n6 s$ b( ^' r: q5 I; G: a& wado_stream.open
4 h3 o! y- \1 a7 |3 L# [" D0 d/ H( p% v/ Z6 `! ?% q
if not bol_PartStart then( N- z& e! @% i1 Z6 J# F
4 V# i- {& y8 m& Q( e7 J' V! c3 ~0 H; ^# s ado_stream.LoadFromFile(server.mappath(".") "/" str_filename) ' 读取文件1 @! t$ p2 }4 o+ s" u$ y& w
6 T/ m6 F# H4 |& n2 K! ]: v) S
ado_stream.position = ado_stream.size % d5 N3 o) I3 l9 a
& H+ t5 c' m X! T7 F" _+ [! E9 p5 eend if
9 A' f7 P; e0 {1 g: P; B7 x/ D/ w2 i5 T
ado_stream.Write xml_data.nodeTypedValue $ h5 J* f+ g+ `, r, Q
/ \8 F5 d7 T) Y; U
' 文件存盘
' e6 V: s7 I I% O: M8 O( M5 w L7 o" f- d7 c0 T
ado_stream.SaveToFile server.mappath(".") "/" str_filename,2
$ a( U$ K _* j- f- ~1 h# S1 v l7 |% L8 u, P" G' m9 S/ q
'保存文件 2=adSaveCreateOverWrite
6 Q0 W1 I' F9 X- N) _9 Z3 l
. ~7 V/ d( J. Y$ e4 kado_stream.close ! Y' }# P0 b% D# T% n5 z
" X% Q" N6 V) C
9 c4 y1 p4 s* y8 l8 D" B3 x+ y
9 v; k$ y/ A8 ~, d8 X' 释放资源
/ g4 O, u U" D& O( u6 ]1 b: w
* u* Y" X7 U9 e% [1 b; Nset ado_stream = Nothing
{* ^- P$ O% Y" g+ k' s
4 b+ H7 q- g& T( Gset xml_dom = Nothing - s/ \6 c0 g4 O# |$ s& n
8 ^! d2 X, r; j, k& U' ]; F' 向浏览器返回信息
& z3 j8 D1 H- F, E1 F6 d2 L+ ]' U6 b8 y
Response.Write "Upload successful!" str_filename int_PartID bol_PartStart2 L- I/ o, Y8 [1 Z# s; L& ~) M
1 T5 M( i3 [5 `! W0 G$ t8 l%
; X0 }: s" ~$ l4 b( q- c9 ~: g
, Q. Q' t0 @: T[Ctrl A 全部选择 提示:你可先修改部分代码,再按运行]1 j8 Q* m3 ?' [' ^
3 h% s* z, T: x( A' M" A另外:此文的目的并不是说这个程序能给朋友们解决什么问题,主要目的还是为了和大家交流一些心得:$ g1 |. ]* W6 F9 i1 {( E
碰到问题-发现问题-解决问题.
1 Q3 D" s; \" k希望大家都不要成为一个标准的代码机器人。
' y! t0 _% d9 |: M& B多学、多看、多思考、多实践。
8 x% a+ w* t* t5 R没有什么是不能解决的。
点击图标进入精品网摘收藏 欢迎大家加入网络收藏夹