php中关于普通表单多文件上传的处理方法
程序员文章站
2023-09-09 18:13:58
然而有些情况只需要传递几个文件,而且文件体积并不太大,这种情况下使用组件则有点牛刀杀鸡的感觉,通过html自带的表单就可以...
然而有些情况只需要传递几个文件,而且文件体积并不太大,这种情况下使用组件则有点牛刀杀鸡的感觉,通过html自带的<input type="file">表单就可以实现需要的功能,关键在于后台接收程序的处理。
php处理上传做的很方便,上传文件的信息通过服务器自动处理到$_files数组中,开发者只需要使用的内置处理函数简单操作就可以啦。asp开发者则没有这么幸运,官方并没有提供直接的处理方法,需要开发者自己设计,这时就需要开发者了解iis对enctype="multipart/form-data"表单的处理方式,iis把enctype="multipart/form-data"表单提交的数据存储成二进制数据,以二进制格式返回给开发者,开发者则需要通过lenb、midb的字节处理函数来分析获取的上传内容,客户端发送的具体表单数据格式,可以了解下http rfc1867协议传输格式方面的知识。
下面是我处理多个文件上传的方法,包括php和asp两个版本。
php:website_dirroot代表网站根目录:
<?php
/*
* class: 文件上传类
* author: 51js.com-zmm
* date: 2011.1.20
* email: 304924248@qq.com
* blog: http://www.cnblogs.com/cnzmm/
*/
class upload {
public $up_ext=array(), $up_max=5210, $up_dir;
private $up_name, $up_rename=true, $up_num=0, $up_files=array(), $up_ret=array();
function __construct($name, $ext=array(), $rename=true) {
if (!empty($name)) {
$this->up_name = $name;
!empty($ext) && $this->up_ext = $ext;
$this->up_rename = $rename;
$this->up_dir = website_dirroot.
$globals['cfg_upload_path'];
$this->initupload();
} else {
exit('upload文件域名称为空,初始化失败!');
}
}
private function initupload() {
if (is_array($_files[$this->up_name])) {
$up_arr = count($_files[$this->up_name]);
$up_all = count($_files[$this->up_name], 1);
$up_cnt = ($up_all - $up_arr) / $up_arr;
for ($i = 0; $i < $up_cnt; $i ++) {
if ($_files[$this->up_name]['error'][$i] != 4) {
$this->up_files[] = array(
'tmp_name' => $_files[$this->up_name]['tmp_name'][$i],
'name' => $_files[$this->up_name]['name'][$i],
'type' => $_files[$this->up_name]['type'][$i],
'size' => $_files[$this->up_name]['size'][$i],
'error' => $_files[$this->up_name]['error'][$i]
);
}
}
$this->up_num = count($this->up_files);
} else {
if (isset($_files[$this->up_name])) {
$this->up_files = array(
'tmp_name' => $_files[$this->up_name]['tmp_name'],
'name' => $_files[$this->up_name]['name'],
'type' => $_files[$this->up_name]['type'],
'size' => $_files[$this->up_name]['size'],
'error' => $_files[$this->up_name]['error']
);
$this->up_num = 1;
} else {
exit('没找找到需要upload的文件!');
}
}
$this->chkupload();
}
private function chkupload() {
if (empty($this->up_ext)) {
$up_mime = array('image/wbmp', 'image/bmp', 'image/gif', 'image/pjpeg', 'image/x-png');
foreach ($this->up_files as $up_file) {
$up_allw = false;
foreach ($up_mime as $mime) {
if ($up_file['type'] == $mime) {
$up_allw = true; break;
}
}
!$up_allw && exit('不允许上传'.$up_file['type'].'格式的文件!');
if ($up_file['size'] / 1024 > $this->up_max) {
exit('不允许上传大于 '.$this->up_max.'k 的文件!');
}
}
} else {
foreach ($this->up_files as $up_file) {
$up_ext = end(explode('.', $up_file['name']));
$up_allw = false;
foreach ($this->up_ext as $ext) {
if ($up_ext == $ext) {
$up_allw = true; break;
}
}
!$up_allw && exit('不允许上传.'.$up_ext.'格式的文件!');
if ($up_file['size'] / 1024 > $this->up_max) {
exit('不允许上传大于 '.$this->up_max.'k 的文件!');
}
}
}
$this->uploading();
}
private function uploading() {
if (io::dircreate($this->up_dir)) {
if (chmod($this->up_dir, 0777)) {
if (!empty($this->up_files)) {
foreach ($this->up_files as $up_file) {
if (is_uploaded_file($up_file['tmp_name'])) {
$file_name = $up_file['name'];
if ($this->up_rename) {
$file_ext = end(explode('.', $file_name));
$file_rnd = substr(md5(uniqid()), mt_rand(0, 26), 6);
$file_name = date('ymdhis').'_'.$file_rnd.'.'.$file_ext;
}
$file_name = $this->up_dir.'/'.$file_name;
if (move_uploaded_file($up_file['tmp_name'], $file_name)) {
$this->up_ret[] = str_replace(website_dirroot, '', $file_name);
} else {
exit('文件上传失败!');
}
}
}
}
} else {
exit('未开启写入权限!');
}
} else {
exit('上传目录创建失败!');
}
}
public function getupload() {
return empty($this->up_ret) ? false : $this->up_ret;
}
function __destruct() {}
}
?>
asp:
<%
class multiupload
rem public-variant
public form, isfinished
private bvbcrlf, bseparate, fpassed, formdata, filetype, filesize, folderpath, _
frename, fimgonly, itemcount, chunksize, btime, serrors, sauthor, sversion
private itemstart(), itemlength(), datastart(), datalength(), itemname(), itemdata(), extenarr(), httparr()
rem class-initialize
private sub class_initialize
call initvariant
server.scripttimeout = 1800
set form = server.createobject("scripting.dictionary")
sauthor = "51js.com-zmm"
sversion = "multiupload class 3.0"
end sub
rem class-attributes
public property let allowtype(byval stype)
dim regex
set regex = new regexp
regex.pattern = "^(\w+\|)*\w+$"
regex.global = false
regex.ignorecase = true
if regex.test(stype) then filetype = "|" & ucase(stype) & "|"
set regex = nothing
end property
public property let maxsize(byval ssize)
if isnumeric(ssize) then filesize = cdbl(formatnumber(ccur(ssize), 2))
end property
public property let savefolder(byval sfolder)
folderpath = sfolder
end property
public property let commonpassed(byval bcheck)
fpassed = bcheck
end property
public property let filerenamed(byval brename)
frename = brename
end property
public property let fileisallimg(byval bonly)
fimgonly = bonly
end property
public property get savefolder
savefolder = folderpath
end property
public property get filerenamed
filerenamed = frename
end property
public property get fileisallimg
fileisallimg = fimgonly
end property
public property get errmessage
errmessage = serrors
end property
public property get clsauthor
clsauthor = sauthor
end property
public property get clsversion
clsversion = sversion
end property
rem class-methods
private function initvariant
isfinished = false
bvbcrlf = strtobyte(vbcrlf & vbcrlf)
bseparate = strtobyte(string(29, "-"))
fpassed = false
filetype = "*"
filesize = "*"
frename = true
fimgonly = true
itemcount = 0
chunksize = 1024 * 128
btime = now
serrors = ""
end function
public function getuploaddata
dim curread : curread = 0
dim datalen : datalen = request.totalbytes
dim appname : appname = "progress" & iptonum(getclientipaddr)
dim streamtmp
set streamtmp = server.createobject("adodb.stream")
streamtmp.type = 1
streamtmp.open
do while curread < datalen
dim partlen : partlen = chunksize
if partlen + curread > datalen then partlen = datalen - curread
streamtmp.write request.binaryread(partlen)
curread = curread + partlen
letprogress appname, array(curread, datalen, datediff("s", btime, now), folderpath)
loop
streamtmp.position = 0
formdata = streamtmp.read(datalen)
streamtmp.close
set streamtmp = nothing
call itemposition
end function
private function letprogress(byval sname, byval varr)
application.value(sname) = join(varr, "|")
end function
private function delprogress
application.contents.remove("progress" & iptonum(getclientipaddr))
end function
private function itemposition
dim istart, ilength : istart = 1
do until instrb(istart, formdata, bseparate) = 0
istart = instrb(istart, formdata, bseparate) + lenb(bseparate) + 14
ilength = instrb(istart, formdata, bseparate) - istart - 2
if abs(istart + 2 - lenb(formdata)) > 2 then
redim preserve itemstart(itemcount)
redim preserve itemlength(itemcount)
itemstart(itemcount) = istart
itemlength(itemcount) = ilength
itemcount = itemcount + 1
end if
loop
call fillitemvalue
end function
private function fillitemvalue
dim datapart, binfor
dim istart : istart = 1
dim icount : icount = 0
dim icheck : icheck = strtobyte("filename")
for i = 0 to itemcount - 1
redim preserve itemname(icount)
redim preserve itemdata(icount)
redim preserve extenarr(icount)
redim preserve httparr(icount)
redim preserve datastart(icount)
redim preserve datalength(icount)
datapart = midb(formdata, itemstart(i), itemlength(i))
istart = instrb(1, datapart, chrb(34)) + 1
ilength = instrb(istart, datapart, chrb(34)) - istart
itemname(icount) = getitemname(midb(datapart, istart, ilength))
istart = instrb(1, datapart, bvbcrlf) + 4
ilength = lenb(datapart) - istart + 1
if instrb(1, datapart, icheck) > 0 then
binfor = midb(datapart, 1, istart - 5)
extenarr(icount) = fileextenname(binfor)
httparr(icount) = gethttpcontent(binfor)
if isnothing(extenarr(icount)) then
itemdata(icount) = ""
datastart(icount) = ""
datalength(icount) = ""
else
if mid(folderpath, len(folderpath) - 1) = "/" then
if frename then
itemdata(icount) = folderpath & getrandomname(6) & extenarr(icount)
else
itemdata(icount) = folderpath & getclientname(binfor) & extenarr(icount)
end if
else
if frename then
itemdata(icount) = folderpath & "/" & getrandomname(6) & extenarr(icount)
else
itemdata(icount) = folderpath & "/" & getclientname(binfor) & extenarr(icount)
end if
end if
datastart(icount) = itemstart(i) + istart - 2
datalength(icount) = ilength
end if
else
extenarr(icount) = ""
httparr(icount) = ""
itemdata(icount) = bytetostr(midb(datapart, istart, ilength))
datastart(icount) = ""
datalength(icount) = ""
end if
icount = icount + 1
next
call itemtocoll
end function
private function getitemname(byval bname)
getitemname = bytetostr(bname)
end function
private function itemtocoll
for i = 0 to itemcount - 1
if not form.exists(itemname(i)) then
form.add itemname(i), itemdata(i)
end if
next
end function
private function fileextenname(byval binfor)
dim pcontent, regex
pcontent = getclientpath(binfor)
if isnothing(pcontent) then
fileextenname = ""
else
set regex = new regexp
regex.pattern = "^.+(\.[^\.]+)$"
regex.global = false
regex.ignorecase = true
fileextenname = regex.replace(pcontent, "$1")
set regex = nothing
end if
end function
private function gethttpcontent(byval binfor)
dim sinfor, regex
sinfor = bytetostr(binfor)
set regex = new regexp
regex.pattern = "^[\s\s]+content-type:([\s\s]+)$"
regex.global = false
regex.ignorecase = true
gethttpcontent = trim(regex.replace(sinfor, "$1"))
set regex = nothing
end function
private function getrandomname(byval slen)
dim regex, stemp, arrfields, n : n = 0
set regex = new regexp
regex.pattern = "[^\d]+"
regex.global = true
regex.ignorecase = true
stemp = regex.replace(now, "") & "-"
set regex = nothing
arrfields = array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", _
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", _
"k", "l", "m", "n", "o", "p", "q", "r", "s", "t", _
"u", "v", "w", "x", "y", "z", "a", "b", "c", "d", _
"e", "f", "g", "h", "i", "j", "k", "l", "m", "n", _
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", _
"y", "z")
randomize
do while n < slen
stemp = stemp & cstr(arrfields(61 * rnd))
n = n + 1
loop
getrandomname = stemp
end function
private function getclientname(byval binfor)
dim pcontent, regex
pcontent = getclientpath(binfor)
if isnothing(pcontent) then
getclientname = ""
else
set regex = new regexp
regex.pattern = "^.*\\([^\.]*)[^\\]+$"
regex.global = false
regex.ignorecase = true
getclientname = regex.replace(pcontent, "$1")
set regex = nothing
end if
end function
private function getclientpath(byval binfor)
dim sinfor, pstart, plength, pcontent
sinfor = bytetostr(binfor)
pstart = instr(1, sinfor, "filename=" & chr(34)) + 10
plength = instr(pstart, sinfor, chr(34)) - pstart
pcontent = mid(sinfor, pstart, plength)
getclientpath = pcontent
end function
public function saveuploadfile
dim isvalidate
dim filepath, ostreamget, ostreamput
isvalidate = fpassed and checkfile
if isvalidate then
for i = 0 to itemcount - 1
if not isnothing(datastart(i)) and not isnothing(datalength(i)) then
if datalength(i) = 0 then
itemdata(i) = ""
else
filepath = server.mappath(itemdata(i))
if createfolder("|", parentfolder(filepath)) then
set ostreamget = server.createobject("adodb.stream")
ostreamget.type = 1
ostreamget.mode = 3
ostreamget.open
ostreamget.write formdata
ostreamget.position = datastart(i)
set ostreamput = server.createobject("adodb.stream")
ostreamput.type = 1
ostreamput.mode = 3
ostreamput.open
ostreamput.write ostreamget.read(datalength(i))
ostreamput.savetofile filepath, 2
ostreamget.close
set ostreamget = nothing
ostreamput.close
set ostreamput = nothing
end if
end if
end if
next
isfinished = true
else
isfinished = false
end if
end function
private function checkfile
dim oboolean : oboolean = true
checkfile = oboolean and checktype and checksize
end function
private function checktype
dim oboolean : oboolean = true
if filetype = "*" then
oboolean = oboolean and true
else
for i = 0 to itemcount - 1
if not isnothing(extenarr(i)) then
if instr(1, filetype, "|" & ucase(mid(extenarr(i), 2)) & "|") > 0 then
if fimgonly then
dim sallow : sallow = "|gif|pjpeg|x-png|bmp|"
dim acheck : acheck = split(ucase(httparr(i)), "/")
dim icheck : icheck = "|" & acheck(ubound(acheck)) & "|"
if instr(1, sallow, icheck, 1) > 0 then
oboolean = oboolean and true
else
serrors = serrors & "表单 [ " & itemname(i) & " ] 的文件格式错误!\n" & _
"支持的格式为:" & replace(mid(filetype, 2, len(filetype) - 1), "|", " ") & "\n\n"
oboolean = oboolean and false
end if
else
oboolean = oboolean and true
end if
else
serrors = serrors & "表单 [ " & itemname(i) & " ] 的文件格式错误!\n" & _
"支持的格式为:" & replace(mid(filetype, 2, len(filetype) - 1), "|", " ") & "\n\n"
oboolean = oboolean and false
end if
end if
next
end if
checktype = oboolean
end function
private function checksize
dim oboolean : oboolean = true
if filesize = "*" then
oboolean = oboolean and true
else
for i = 0 to itemcount - 1
if not isnothing(datalength(i)) then
dim tmpsize : tmpsize = cdbl(formatnumber(ccur(datalength(i)) / 1024, 2))
if tmpsize <= filesize then
oboolean = oboolean and true
else
serrors = serrors & "表单 [ " & itemname(i) & " ] 的文件大小 (" & tmpsize & " kb) 超出范围!\n" & _
"支持大小范围:<= " & filesize & " kb\n\n"
oboolean = oboolean and false
end if
end if
next
end if
checksize = oboolean
end function
private function createfolder(byval sline, byval spath)
dim ofso
set ofso = server.createobject("scripting.filesystemobject")
if not ofso.folderexists(spath) then
dim regex
set regex = new regexp
regex.pattern = "^(.*)\\([^\\]*)$"
regex.global = false
regex.ignorecase = true
sline = sline & regex.replace(spath, "$2") & "|"
spath = regex.replace(spath, "$1")
if createfolder(sline, spath) then createfolder = true
set regex = nothing
else
if sline = "|" then
createfolder = true
else
dim stemp : stemp = mid(sline, 2, len(sline) - 2)
if instrrev(stemp, "|") = 0 then
sline = "|"
spath = spath & "\" & stemp
else
dim folder : folder = mid(stemp, instrrev(stemp, "|") + 1)
sline = "|" & mid(stemp, 1, instrrev(stemp, "|") - 1) & "|"
spath = spath & "\" & folder
end if
ofso.createfolder spath
if createfolder(sline, spath) then createfolder = true
end if
end if
set ofso = nothing
end function
private function parentfolder(byval spath)
dim regex
set regex = new regexp
regex.pattern = "^(.*)\\[^\\]*$"
regex.global = true
regex.ignorecase = true
parentfolder = regex.replace(spath, "$1")
set regex = nothing
end function
private function isnothing(byval svar)
isnothing = cbool(svar = empty)
end function
private function strpadleft(byval stext, byval slen, byval schar)
dim stemp : stemp = stext
do while len(stemp) < slen : stemp = schar & stemp : loop
strpadleft = stemp
end function
private function strtobyte(byval stext)
for i = 1 to len(stext)
strtobyte = strtobyte & chrb(asc(mid(stext, i, 1)))
next
end function
private function bytetostr(byval sbyte)
dim ostream
set ostream = server.createobject("adodb.stream")
ostream.type = 2
ostream.mode = 3
ostream.open
ostream.writetext sbyte
ostream.position = 0
ostream.charset = "gb2312"
ostream.position = 2
bytetostr = ostream.readtext
ostream.close
set ostream = nothing
end function
private function getclientipaddr
if isnothing(getservervar("http_x_forwarded_for")) then
getclientipaddr = getservervar("remote_addr")
else
getclientipaddr = getservervar("http_x_forwarded_for")
end if
end function
private function getservervar(byval stext)
getservervar = request.servervariables(stext)
end function
private function iptonum(byval sip)
dim sip_1, sip_2, sip_3, sip_4
if isnumeric(left(sip, 2)) then
sip_1 = left(sip, instr(sip, ".") - 1)
sip = mid(sip, instr(sip, ".") + 1)
sip_2 = left(sip, instr(sip, ".") - 1)
sip = mid(sip, instr(sip, ".") + 1)
sip_3 = left(sip, instr(sip, ".") - 1)
sip_4 = mid(sip, instr(sip, ".") + 1)
end if
iptonum = cint(sip_1) * 256 * 256 * 256 + cint(sip_2) * 256 * 256 + cint(sip_3) * 256 + cint(sip_4) - 1
end function
rem class-terminate
private sub class_terminate
call delprogress
form.removeall
set form = nothing
end sub
end class
%>
php处理上传做的很方便,上传文件的信息通过服务器自动处理到$_files数组中,开发者只需要使用的内置处理函数简单操作就可以啦。asp开发者则没有这么幸运,官方并没有提供直接的处理方法,需要开发者自己设计,这时就需要开发者了解iis对enctype="multipart/form-data"表单的处理方式,iis把enctype="multipart/form-data"表单提交的数据存储成二进制数据,以二进制格式返回给开发者,开发者则需要通过lenb、midb的字节处理函数来分析获取的上传内容,客户端发送的具体表单数据格式,可以了解下http rfc1867协议传输格式方面的知识。
下面是我处理多个文件上传的方法,包括php和asp两个版本。
php:website_dirroot代表网站根目录:
复制代码 代码如下:
<?php
/*
* class: 文件上传类
* author: 51js.com-zmm
* date: 2011.1.20
* email: 304924248@qq.com
* blog: http://www.cnblogs.com/cnzmm/
*/
class upload {
public $up_ext=array(), $up_max=5210, $up_dir;
private $up_name, $up_rename=true, $up_num=0, $up_files=array(), $up_ret=array();
function __construct($name, $ext=array(), $rename=true) {
if (!empty($name)) {
$this->up_name = $name;
!empty($ext) && $this->up_ext = $ext;
$this->up_rename = $rename;
$this->up_dir = website_dirroot.
$globals['cfg_upload_path'];
$this->initupload();
} else {
exit('upload文件域名称为空,初始化失败!');
}
}
private function initupload() {
if (is_array($_files[$this->up_name])) {
$up_arr = count($_files[$this->up_name]);
$up_all = count($_files[$this->up_name], 1);
$up_cnt = ($up_all - $up_arr) / $up_arr;
for ($i = 0; $i < $up_cnt; $i ++) {
if ($_files[$this->up_name]['error'][$i] != 4) {
$this->up_files[] = array(
'tmp_name' => $_files[$this->up_name]['tmp_name'][$i],
'name' => $_files[$this->up_name]['name'][$i],
'type' => $_files[$this->up_name]['type'][$i],
'size' => $_files[$this->up_name]['size'][$i],
'error' => $_files[$this->up_name]['error'][$i]
);
}
}
$this->up_num = count($this->up_files);
} else {
if (isset($_files[$this->up_name])) {
$this->up_files = array(
'tmp_name' => $_files[$this->up_name]['tmp_name'],
'name' => $_files[$this->up_name]['name'],
'type' => $_files[$this->up_name]['type'],
'size' => $_files[$this->up_name]['size'],
'error' => $_files[$this->up_name]['error']
);
$this->up_num = 1;
} else {
exit('没找找到需要upload的文件!');
}
}
$this->chkupload();
}
private function chkupload() {
if (empty($this->up_ext)) {
$up_mime = array('image/wbmp', 'image/bmp', 'image/gif', 'image/pjpeg', 'image/x-png');
foreach ($this->up_files as $up_file) {
$up_allw = false;
foreach ($up_mime as $mime) {
if ($up_file['type'] == $mime) {
$up_allw = true; break;
}
}
!$up_allw && exit('不允许上传'.$up_file['type'].'格式的文件!');
if ($up_file['size'] / 1024 > $this->up_max) {
exit('不允许上传大于 '.$this->up_max.'k 的文件!');
}
}
} else {
foreach ($this->up_files as $up_file) {
$up_ext = end(explode('.', $up_file['name']));
$up_allw = false;
foreach ($this->up_ext as $ext) {
if ($up_ext == $ext) {
$up_allw = true; break;
}
}
!$up_allw && exit('不允许上传.'.$up_ext.'格式的文件!');
if ($up_file['size'] / 1024 > $this->up_max) {
exit('不允许上传大于 '.$this->up_max.'k 的文件!');
}
}
}
$this->uploading();
}
private function uploading() {
if (io::dircreate($this->up_dir)) {
if (chmod($this->up_dir, 0777)) {
if (!empty($this->up_files)) {
foreach ($this->up_files as $up_file) {
if (is_uploaded_file($up_file['tmp_name'])) {
$file_name = $up_file['name'];
if ($this->up_rename) {
$file_ext = end(explode('.', $file_name));
$file_rnd = substr(md5(uniqid()), mt_rand(0, 26), 6);
$file_name = date('ymdhis').'_'.$file_rnd.'.'.$file_ext;
}
$file_name = $this->up_dir.'/'.$file_name;
if (move_uploaded_file($up_file['tmp_name'], $file_name)) {
$this->up_ret[] = str_replace(website_dirroot, '', $file_name);
} else {
exit('文件上传失败!');
}
}
}
}
} else {
exit('未开启写入权限!');
}
} else {
exit('上传目录创建失败!');
}
}
public function getupload() {
return empty($this->up_ret) ? false : $this->up_ret;
}
function __destruct() {}
}
?>
asp:
复制代码 代码如下:
<%
class multiupload
rem public-variant
public form, isfinished
private bvbcrlf, bseparate, fpassed, formdata, filetype, filesize, folderpath, _
frename, fimgonly, itemcount, chunksize, btime, serrors, sauthor, sversion
private itemstart(), itemlength(), datastart(), datalength(), itemname(), itemdata(), extenarr(), httparr()
rem class-initialize
private sub class_initialize
call initvariant
server.scripttimeout = 1800
set form = server.createobject("scripting.dictionary")
sauthor = "51js.com-zmm"
sversion = "multiupload class 3.0"
end sub
rem class-attributes
public property let allowtype(byval stype)
dim regex
set regex = new regexp
regex.pattern = "^(\w+\|)*\w+$"
regex.global = false
regex.ignorecase = true
if regex.test(stype) then filetype = "|" & ucase(stype) & "|"
set regex = nothing
end property
public property let maxsize(byval ssize)
if isnumeric(ssize) then filesize = cdbl(formatnumber(ccur(ssize), 2))
end property
public property let savefolder(byval sfolder)
folderpath = sfolder
end property
public property let commonpassed(byval bcheck)
fpassed = bcheck
end property
public property let filerenamed(byval brename)
frename = brename
end property
public property let fileisallimg(byval bonly)
fimgonly = bonly
end property
public property get savefolder
savefolder = folderpath
end property
public property get filerenamed
filerenamed = frename
end property
public property get fileisallimg
fileisallimg = fimgonly
end property
public property get errmessage
errmessage = serrors
end property
public property get clsauthor
clsauthor = sauthor
end property
public property get clsversion
clsversion = sversion
end property
rem class-methods
private function initvariant
isfinished = false
bvbcrlf = strtobyte(vbcrlf & vbcrlf)
bseparate = strtobyte(string(29, "-"))
fpassed = false
filetype = "*"
filesize = "*"
frename = true
fimgonly = true
itemcount = 0
chunksize = 1024 * 128
btime = now
serrors = ""
end function
public function getuploaddata
dim curread : curread = 0
dim datalen : datalen = request.totalbytes
dim appname : appname = "progress" & iptonum(getclientipaddr)
dim streamtmp
set streamtmp = server.createobject("adodb.stream")
streamtmp.type = 1
streamtmp.open
do while curread < datalen
dim partlen : partlen = chunksize
if partlen + curread > datalen then partlen = datalen - curread
streamtmp.write request.binaryread(partlen)
curread = curread + partlen
letprogress appname, array(curread, datalen, datediff("s", btime, now), folderpath)
loop
streamtmp.position = 0
formdata = streamtmp.read(datalen)
streamtmp.close
set streamtmp = nothing
call itemposition
end function
private function letprogress(byval sname, byval varr)
application.value(sname) = join(varr, "|")
end function
private function delprogress
application.contents.remove("progress" & iptonum(getclientipaddr))
end function
private function itemposition
dim istart, ilength : istart = 1
do until instrb(istart, formdata, bseparate) = 0
istart = instrb(istart, formdata, bseparate) + lenb(bseparate) + 14
ilength = instrb(istart, formdata, bseparate) - istart - 2
if abs(istart + 2 - lenb(formdata)) > 2 then
redim preserve itemstart(itemcount)
redim preserve itemlength(itemcount)
itemstart(itemcount) = istart
itemlength(itemcount) = ilength
itemcount = itemcount + 1
end if
loop
call fillitemvalue
end function
private function fillitemvalue
dim datapart, binfor
dim istart : istart = 1
dim icount : icount = 0
dim icheck : icheck = strtobyte("filename")
for i = 0 to itemcount - 1
redim preserve itemname(icount)
redim preserve itemdata(icount)
redim preserve extenarr(icount)
redim preserve httparr(icount)
redim preserve datastart(icount)
redim preserve datalength(icount)
datapart = midb(formdata, itemstart(i), itemlength(i))
istart = instrb(1, datapart, chrb(34)) + 1
ilength = instrb(istart, datapart, chrb(34)) - istart
itemname(icount) = getitemname(midb(datapart, istart, ilength))
istart = instrb(1, datapart, bvbcrlf) + 4
ilength = lenb(datapart) - istart + 1
if instrb(1, datapart, icheck) > 0 then
binfor = midb(datapart, 1, istart - 5)
extenarr(icount) = fileextenname(binfor)
httparr(icount) = gethttpcontent(binfor)
if isnothing(extenarr(icount)) then
itemdata(icount) = ""
datastart(icount) = ""
datalength(icount) = ""
else
if mid(folderpath, len(folderpath) - 1) = "/" then
if frename then
itemdata(icount) = folderpath & getrandomname(6) & extenarr(icount)
else
itemdata(icount) = folderpath & getclientname(binfor) & extenarr(icount)
end if
else
if frename then
itemdata(icount) = folderpath & "/" & getrandomname(6) & extenarr(icount)
else
itemdata(icount) = folderpath & "/" & getclientname(binfor) & extenarr(icount)
end if
end if
datastart(icount) = itemstart(i) + istart - 2
datalength(icount) = ilength
end if
else
extenarr(icount) = ""
httparr(icount) = ""
itemdata(icount) = bytetostr(midb(datapart, istart, ilength))
datastart(icount) = ""
datalength(icount) = ""
end if
icount = icount + 1
next
call itemtocoll
end function
private function getitemname(byval bname)
getitemname = bytetostr(bname)
end function
private function itemtocoll
for i = 0 to itemcount - 1
if not form.exists(itemname(i)) then
form.add itemname(i), itemdata(i)
end if
next
end function
private function fileextenname(byval binfor)
dim pcontent, regex
pcontent = getclientpath(binfor)
if isnothing(pcontent) then
fileextenname = ""
else
set regex = new regexp
regex.pattern = "^.+(\.[^\.]+)$"
regex.global = false
regex.ignorecase = true
fileextenname = regex.replace(pcontent, "$1")
set regex = nothing
end if
end function
private function gethttpcontent(byval binfor)
dim sinfor, regex
sinfor = bytetostr(binfor)
set regex = new regexp
regex.pattern = "^[\s\s]+content-type:([\s\s]+)$"
regex.global = false
regex.ignorecase = true
gethttpcontent = trim(regex.replace(sinfor, "$1"))
set regex = nothing
end function
private function getrandomname(byval slen)
dim regex, stemp, arrfields, n : n = 0
set regex = new regexp
regex.pattern = "[^\d]+"
regex.global = true
regex.ignorecase = true
stemp = regex.replace(now, "") & "-"
set regex = nothing
arrfields = array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", _
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", _
"k", "l", "m", "n", "o", "p", "q", "r", "s", "t", _
"u", "v", "w", "x", "y", "z", "a", "b", "c", "d", _
"e", "f", "g", "h", "i", "j", "k", "l", "m", "n", _
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", _
"y", "z")
randomize
do while n < slen
stemp = stemp & cstr(arrfields(61 * rnd))
n = n + 1
loop
getrandomname = stemp
end function
private function getclientname(byval binfor)
dim pcontent, regex
pcontent = getclientpath(binfor)
if isnothing(pcontent) then
getclientname = ""
else
set regex = new regexp
regex.pattern = "^.*\\([^\.]*)[^\\]+$"
regex.global = false
regex.ignorecase = true
getclientname = regex.replace(pcontent, "$1")
set regex = nothing
end if
end function
private function getclientpath(byval binfor)
dim sinfor, pstart, plength, pcontent
sinfor = bytetostr(binfor)
pstart = instr(1, sinfor, "filename=" & chr(34)) + 10
plength = instr(pstart, sinfor, chr(34)) - pstart
pcontent = mid(sinfor, pstart, plength)
getclientpath = pcontent
end function
public function saveuploadfile
dim isvalidate
dim filepath, ostreamget, ostreamput
isvalidate = fpassed and checkfile
if isvalidate then
for i = 0 to itemcount - 1
if not isnothing(datastart(i)) and not isnothing(datalength(i)) then
if datalength(i) = 0 then
itemdata(i) = ""
else
filepath = server.mappath(itemdata(i))
if createfolder("|", parentfolder(filepath)) then
set ostreamget = server.createobject("adodb.stream")
ostreamget.type = 1
ostreamget.mode = 3
ostreamget.open
ostreamget.write formdata
ostreamget.position = datastart(i)
set ostreamput = server.createobject("adodb.stream")
ostreamput.type = 1
ostreamput.mode = 3
ostreamput.open
ostreamput.write ostreamget.read(datalength(i))
ostreamput.savetofile filepath, 2
ostreamget.close
set ostreamget = nothing
ostreamput.close
set ostreamput = nothing
end if
end if
end if
next
isfinished = true
else
isfinished = false
end if
end function
private function checkfile
dim oboolean : oboolean = true
checkfile = oboolean and checktype and checksize
end function
private function checktype
dim oboolean : oboolean = true
if filetype = "*" then
oboolean = oboolean and true
else
for i = 0 to itemcount - 1
if not isnothing(extenarr(i)) then
if instr(1, filetype, "|" & ucase(mid(extenarr(i), 2)) & "|") > 0 then
if fimgonly then
dim sallow : sallow = "|gif|pjpeg|x-png|bmp|"
dim acheck : acheck = split(ucase(httparr(i)), "/")
dim icheck : icheck = "|" & acheck(ubound(acheck)) & "|"
if instr(1, sallow, icheck, 1) > 0 then
oboolean = oboolean and true
else
serrors = serrors & "表单 [ " & itemname(i) & " ] 的文件格式错误!\n" & _
"支持的格式为:" & replace(mid(filetype, 2, len(filetype) - 1), "|", " ") & "\n\n"
oboolean = oboolean and false
end if
else
oboolean = oboolean and true
end if
else
serrors = serrors & "表单 [ " & itemname(i) & " ] 的文件格式错误!\n" & _
"支持的格式为:" & replace(mid(filetype, 2, len(filetype) - 1), "|", " ") & "\n\n"
oboolean = oboolean and false
end if
end if
next
end if
checktype = oboolean
end function
private function checksize
dim oboolean : oboolean = true
if filesize = "*" then
oboolean = oboolean and true
else
for i = 0 to itemcount - 1
if not isnothing(datalength(i)) then
dim tmpsize : tmpsize = cdbl(formatnumber(ccur(datalength(i)) / 1024, 2))
if tmpsize <= filesize then
oboolean = oboolean and true
else
serrors = serrors & "表单 [ " & itemname(i) & " ] 的文件大小 (" & tmpsize & " kb) 超出范围!\n" & _
"支持大小范围:<= " & filesize & " kb\n\n"
oboolean = oboolean and false
end if
end if
next
end if
checksize = oboolean
end function
private function createfolder(byval sline, byval spath)
dim ofso
set ofso = server.createobject("scripting.filesystemobject")
if not ofso.folderexists(spath) then
dim regex
set regex = new regexp
regex.pattern = "^(.*)\\([^\\]*)$"
regex.global = false
regex.ignorecase = true
sline = sline & regex.replace(spath, "$2") & "|"
spath = regex.replace(spath, "$1")
if createfolder(sline, spath) then createfolder = true
set regex = nothing
else
if sline = "|" then
createfolder = true
else
dim stemp : stemp = mid(sline, 2, len(sline) - 2)
if instrrev(stemp, "|") = 0 then
sline = "|"
spath = spath & "\" & stemp
else
dim folder : folder = mid(stemp, instrrev(stemp, "|") + 1)
sline = "|" & mid(stemp, 1, instrrev(stemp, "|") - 1) & "|"
spath = spath & "\" & folder
end if
ofso.createfolder spath
if createfolder(sline, spath) then createfolder = true
end if
end if
set ofso = nothing
end function
private function parentfolder(byval spath)
dim regex
set regex = new regexp
regex.pattern = "^(.*)\\[^\\]*$"
regex.global = true
regex.ignorecase = true
parentfolder = regex.replace(spath, "$1")
set regex = nothing
end function
private function isnothing(byval svar)
isnothing = cbool(svar = empty)
end function
private function strpadleft(byval stext, byval slen, byval schar)
dim stemp : stemp = stext
do while len(stemp) < slen : stemp = schar & stemp : loop
strpadleft = stemp
end function
private function strtobyte(byval stext)
for i = 1 to len(stext)
strtobyte = strtobyte & chrb(asc(mid(stext, i, 1)))
next
end function
private function bytetostr(byval sbyte)
dim ostream
set ostream = server.createobject("adodb.stream")
ostream.type = 2
ostream.mode = 3
ostream.open
ostream.writetext sbyte
ostream.position = 0
ostream.charset = "gb2312"
ostream.position = 2
bytetostr = ostream.readtext
ostream.close
set ostream = nothing
end function
private function getclientipaddr
if isnothing(getservervar("http_x_forwarded_for")) then
getclientipaddr = getservervar("remote_addr")
else
getclientipaddr = getservervar("http_x_forwarded_for")
end if
end function
private function getservervar(byval stext)
getservervar = request.servervariables(stext)
end function
private function iptonum(byval sip)
dim sip_1, sip_2, sip_3, sip_4
if isnumeric(left(sip, 2)) then
sip_1 = left(sip, instr(sip, ".") - 1)
sip = mid(sip, instr(sip, ".") + 1)
sip_2 = left(sip, instr(sip, ".") - 1)
sip = mid(sip, instr(sip, ".") + 1)
sip_3 = left(sip, instr(sip, ".") - 1)
sip_4 = mid(sip, instr(sip, ".") + 1)
end if
iptonum = cint(sip_1) * 256 * 256 * 256 + cint(sip_2) * 256 * 256 + cint(sip_3) * 256 + cint(sip_4) - 1
end function
rem class-terminate
private sub class_terminate
call delprogress
form.removeall
set form = nothing
end sub
end class
%>
下一篇: php ftp文件上传函数(基础版)