欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

php中关于普通表单多文件上传的处理方法

程序员文章站 2022-04-28 15:59:22
然而有些情况只需要传递几个文件,而且文件体积并不太大,这种情况下使用组件则有点牛刀杀鸡的感觉,通过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
%>