基于版本:Discuz! X 2.0
发帖时经常使用flash 批量上传附件,来粗略的了解一下flash上传附件的过程。
在帖子中,当点击编辑器上传按纽 程序读取 ./template/default/forum/editor_menu_forum.htm 模板文件
从编辑模板源文件里面可以看到程序输出了一代码,其中的js- <script type="text/javascript">
- $('{$editorid}_multiimg').innerHTML = AC_FL_RunContent(
- 'width', '470', 'height', '268',
- 'src', '{IMGDIR}/upload.swf?site={$_G[siteroot]}misc.php%3fmod=swfupload%26type=image%26fid=$_G[fid]&type=image&random=<!--{echo random(4)}-->',
- 'quality', 'high',
- 'id', 'swfupload',
- 'menu', 'false',
- 'allowScriptAccess', 'always',
- 'wmode', 'transparent'
- );
- </script>
[color=rgb(51, 102, 153) !important]复制代码
输出 flash
使用 AC_FL_RunContent 函数(此函数在 common.js)来输出 flash
在此函数中 使用 AC_GetArgs 函数来处理 AC_FL_RunContent 所传进来的变量以构造 flash 输出相关的信息
从以上代码的- 'src', '{IMGDIR}/upload.swf?site={$_G[siteroot]}misc.php%3fmod=swfupload%26type=image%26fid=$_G[fid]&type=image&random=<!--{echo random(4)}-->',
[color=rgb(51, 102, 153) !important]复制代码
可以看出 此 flash 的 src 为 论坛后台设定的 IMGDIR 目录下的 upload.swf 输出的 flash 还传进了一段参数
这里面要注意 {IMGDIR} 为后台设定图片目录 或者 ./config/config_global.php中的 $_config['output']['staticurl'] 值 , 有些站长把该值设置了远程的一个地址 于是程序请求得是远程的 upload.swf ,当文件上传完成后 upload.swf 会请求相同目录下的 misc.php 文件 这样设置可能就会上传失败- site={$_G[siteroot]}misc.php%3fmod=swfupload%26type=image%26fid=$_G[fid]&type=image&random=<!--{echo random(4)}-->
[color=rgb(51, 102, 153) !important]复制代码
flash 会根据该参数 请求类似 misc.php?mod=swfupload&fid=2&action=swfupload&operation=config 的地址
根据该地址我们很容易找到 misc_swfupload.php 文件,&operation=config 初始化处理后将会输出一个 xml 给 flash。此 xml 里面包括 flash 上传界面的提示文字、上传大小限制、上传文件的限制类型等等,很多时候点上传 flash 按纽空白 没有显示中文件都是因为 xml 输出出错导致
到这里 一切正常 xml 也没出错 我们就可以看到 flash 上传的界面 (终于可以开始上传了....)
点击浏览器按纽,选择需要上传的文件点上传后 flash 会请求到 misc_swfupload.php 此时文件就被php传到 php 所配置的上传的临时路径下
所以,在上传失败时可能的一条原因是 php.ini 中 upload_tmp_dir 所指定的临时上传目录或硬盘是否满了,是否有权限
- } elseif($_G['gp_operation'] == 'upload') {
- require_once libfile('class/forumupload');
- if(empty($_G['gp_simple'])) {
- $_FILES['Filedata']['name'] = addslashes(diconv(urldecode($_FILES['Filedata']['name']), 'UTF-8'));
- $_FILES['Filedata']['type'] = $_G['gp_filetype'];
- }
- $upload = new forum_upload();
- }
[color=rgb(51, 102, 153) !important]复制代码
在此实例化了一个 forum_upload 类( class_forumupload.php ) 在这个类里面使用了 discuz_upload 类( class_upload.php )对文件进行移动处理
程序首先 调用 discuz_upload 里面的 init 方法处理 $_FILES 来得到上传文件的目标路径、文件名、大小等等信息,存在其属性 $attach 数组中
init 方法会调用到 is_image_ext 来判断文件是否属于图片(该方法判断后缀有 'jpg', 'jpeg', 'gif', 'png', 'bmp');
出于安全的考虑 init 中调用到 get_target_extension 方法处理非法的文件后缀(将非 'attach', 'jpg', 'jpeg', 'gif', 'png', 'swf', 'bmp', 'txt', 'zip', 'rar', 'mp3'扩展名名的附件扩展名改成 attach)
然后根据 $attach 里面的各项值 来判断相关的 所上传文件尺寸、大小、类型、当前用户所属用户组上传限制等合法性
当程序判断该附件“合法”,则调用 discuz_upload 类的 save 方法 对图片进行移动,从php 的临时上传目录移到程序附件相对应的目录
save 方法所调用的 save_to_local 兼容使用了 copy、move_uploaded_file、fread/fwrite等三种移动方法
在此我们可以发现需要 data 目录及子目录需要可读写执行权限。
在这里如果有产生错误,
- 'file_upload_error_-101' => '上传失败!上传文件不存在或不合法,请返回。',
- 'file_upload_error_-102' => '上传失败!非图片类型文件,请返回。',
- 'file_upload_error_-103' => '上传失败!无法写入文件或写入失败,请返回。',
- 'file_upload_error_-104' => '上传失败!无法识别的图像文件格式,请返回。',
[color=rgb(51, 102, 153) !important]复制代码
根据文字所对应的数字代码,可以在 class_upload.php 中找到其相对应的判断所进入的判断代码行。
- '-1' : '内部服务器错误',
- '0' : '上传成功',
- '1' : '不支持此类扩展名',
- '2' : '服务器限制无法上传那么大的附件',
- '3' : '用户组限制无法上传那么大的附件',
- '4' : '不支持此类扩展名',
- '5' : '文件类型限制无法上传那么大的附件',
- '6' : '今日你已无法上传更多的附件',
- '7' : '请选择图片文件(' + imgexts + ')',
- '8' : '附件文件无法保存',
- '9' : '没有合法的文件被上传',
- '10' : '非法操作',
- '11' : '今日你已无法上传那么大的附件'
[color=rgb(51, 102, 153) !important]复制代码
上传失败所示提的代码也可以在 class_forumupload.php 里面找到相对应的判断。这样就能很方便的找到问题出错在哪里。
save 成功后 如果所上传文件是图片附件,并且后台开启了生成缩略图,程序会根据上传后的图片进行处理生成缩略图
上传成功,forum_upload 类 使用 getattachnewaid 函数 向 forum_attachment 插入一条记录返回新附件的 aid
并插入一条记录到 forum_attachment_unused 表的中
点确定后返回到附件列表,程序根据aid 向 forum.php?mod=ajax&action=attachlist&aids=|7|6|5&fid=2&inajax=1&ajaxtarget=attachlist 地址请求
该地址处理程序 forum_ajax.php 使用 getattach 函数从数据库中读出附件等信息并将附件展示出来
至此附件上传成功
|