以前,用户在論壇中發一些圖片,會有一部分是從其它的站點直接複製內容過來,這樣複製過來的圖片只是一個附件地址,保存在主題和帖子內容中,一旦其它站點開啓防盜鏈或改動圖片附件的文件夾位置,就會造成圖片不能正常顯示甚至死鏈。同時對站長自己附件的管理也帶來了麻煩,影響網站運行效果。

Discuz!X2.0 中在編輯器中新增加了一鍵下載遠程圖片到本地的功能,一般默認點擊 「高級」,在 「word「下面會有一個按鈕,髮帶有圖片地址的主題或帖子時,按下這個按鈕,就會把圖片下載到本地服務器。

下面介紹一下這個下載到本地服務器的過程。找到 source/module/forum/forum_ajax.php,大約 320 行:

  1. elseif($_G['gp_action'] == 'downremoteimg') {
  2.          $_G['gp_message'] = dstripslashes($_G['gp_message']);
  3.          $_G['gp_message'] = str_replace(array("
    ", "
    ", "
    "), '', $_G['gp_message']);
  4. preg_match_all("/[img]s*([^[<
    ]+?)s*[/img]|[img=d{1,4}[x|,]d{1,4}]s*([^[<
    ]+?)s*[/img]/is",
    $_G['gp_message'], $image1, PREG_SET_ORDER);
  5.          preg_match_all("/<img.+src=('|"|)?(.*)(1)([s].*)?>/ismUe", $_G['gp_message'], $image2, PREG_SET_ORDER);
  6.          $temp = $aids = $existentimg = array();

這段代碼是對內容 $G_[『gp_message』] 刪除由 addslashes() 函數添加的反斜槓,str_replace 替換換行符等,即還原文本;preg_match_all 是對文本中圖片幾種地址進行全局匹配,結果保存在 $image1 、 $ image2 中。初始化變量。

  1. if(is_array($image1) && !empty($image1)) {
  2.    foreach($image1 as $value) {
  3.         $temp[] = array(
  4.                          '0' => $value[0],
  5.                          '1' => trim(!empty($value[1]) ? $value[1] : $value[2])
  6.         );
  7. }
  8. }
  9. if(is_array($image2) && !empty($image2)) {
  10.    foreach($image2 as $value) {
  11.                 $temp[] = array(
  12.                                  '0' => $value[0],
  13.                                  '1' => trim($value[2])
  14.                 );
  15.    }
  16. }
  17. require_once libfile('class/image');

這段是對匹配後的結果進行遍歷賦值,幷包含圖片處理類。

  1. if(is_array($temp) && !empty($temp)) {
  2.            require_once libfile('class/upload');
  3.            $upload = new discuz_upload();
  4.            $attachaids = array();
  5.            foreach($temp as $value) {
  6.                                 …………………中間略去…………………
  7. if(!@$fp = fopen($attach['target'], 'wb')) {
  8.                 continue;
  9. } else {
  10.                 flock($fp, 2);
  11.                 fwrite($fp, $content);
  12.                 fclose($fp);
  13. }
  14. if(!$upload->get_image_info($attach['target'])) {
  15.                 @unlink($attach['target']);
  16.                 continue;
  17. }

這一段的目的是對下載下來的附件進行地址、圖片信息、縮略圖等進行處理,並寫入文件保存,並且判斷是不是圖片,如果不是,則刪除----unlink($attach['target']); 。

  1. $attach['size'] = filesize($attach['target']);
  2.    $upload->attach = $attach;
  3.    $thumb = $width = 0;
  4.    if($upload->attach['isimage']) {
  5.                         …………………中間內容省略………………………
  6.    $aids[] = $aid = getattachnewaid();
  7.    $setarr = array(//得到圖片附件相關信息
  8.                         'aid' => $aid,
  9.                         'dateline' => $_G['timestamp'],
  10.                         'filename' => daddslashes($upload->attach['name']),
  11.                         'filesize' => $upload->attach['size'],
  12.                         'attachment' => $upload->attach['attachment'],
  13.                         'isimage' => $upload->attach['isimage'],
  14.                         'uid' => $_G['uid'],
  15.                         'thumb' => $thumb,
  16.                         'remote' => '0',
  17.                         'width' => $width
  18.    );
  19.    DB::insert("forum_attachment_unused", $setarr);//入庫
  20.    $attachaids[$hash] = $imagereplace['newimageurl'][] = '[attachimg]'.$aid.'[/attachimg]';
  21. } else {
  22.    $imagereplace['newimageurl'][] = $attachaids[$hash];
  23. }

這段是把圖片附件的信息進行處理,通過 getattachnewaid 函數把主題或帖子相關圖片信息插入附件表。

  1. if(!empty($aids)) {
  2.         require_once libfile('function/post');
  3.         ftpupload($aids);
  4. }
  5. $_G['gp_message'] = str_replace($imagereplace['oldimageurl'], $imagereplace['newimageurl'], $_G['gp_message']);
  6. $_G['gp_message'] = addcslashes($_G['gp_message'], '/"');
  7. }

最後這段就是真正把圖片附件上傳到自己本地服務器,並將文本再 addcslashes 處理。