在帖子中,當點選編輯器上傳按紐 程式讀取 ./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>
輸出 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)}-->',
可以看出 此 flash 的 src 為 論壇後臺設定的 IMGDIR 目錄下的 upload.swf 輸出的 flash 還傳進了一段引數
這裡面要注意 {IMGDIR} 為後臺設定圖片目錄 有些站長把該值設定了遠端的一個地址 於是程式請求得是遠端的 upload.swf ,當檔案上傳完成後 upload.swf 會請求相同目錄下的 misc.php 檔案 這樣設定可能就會上傳失敗
- site={$_G[siteroot]}misc.php%3fmod=swfupload%26type=image%26fid=$_G[fid]&type=image&random=<!--{echo random(4)}-->
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();
- }
在此例項化了一個 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' => '上傳失敗!無法識別的影像檔案格式,請返回。',
根據文字所對應的數字程式碼,可以在 class_upload.php 中找到其相對應的判斷所進入的判斷程式碼行。
- '-1' : '內部伺服器錯誤',
- '0' : '上傳成功',
- '1' : '不支援此類副檔名',
- '2' : '伺服器限制無法上傳那麼大的附件',
- '3' : '使用者組限制無法上傳那麼大的附件',
- '4' : '不支援此類副檔名',
- '5' : '檔案型別限制無法上傳那麼大的附件',
- '6' : '今日你已無法上傳更多的附件',
- '7' : '請選擇圖片檔案 (' + imgexts + ')',
- '8' : '附件檔案無法儲存',
- '9' : '沒有合法的檔案被上傳',
- '10' : '非法操作',
- '11' : '今日你已無法上傳那麼大的附件'
上傳失敗所示提的程式碼也可以在 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 函式從資料庫中讀出附件等資訊並將附件展示出來
至此附件上傳成功