Moodle中文文件名上传下载与zip压缩解压缩问题

安裝moodle 1.8.2(OS and Web Server: FreeBSD 6.2 and Apache22, PHP5.1.6)上傳中文檔名的檔案後無法正確顯示中文名問題…

安裝moodle 1.8.2(OS and Web Server: FreeBSD 6.2 and Apache22, PHP5.1.6)上傳中文檔名的檔案後無法正確顯示中文名問題,先到網路搜尋解決方法,在這幾篇看到修正方法:

1.http://moodle.club.tw/moodle/mod/forum/discuss.php?d=66&parent=163 

以下是個人的說明與提出一些修正的看法

於config.php加入

$CFG->unicodecleanfilename = true;
即可正常上傳中文檔名

在lib/moodlelib.php下亦有這段說明

/**
 * Cleans a given filename by removing suspicious or troublesome characters
 * Only these are allowed: alphanumeric _ – .
 * Unicode characters can be enabled by setting $CFG->unicodecleanfilename = true in config.php
 *
 * WARNING: unicode characters may not be compatible with zip compression in backup/restore,
 *          because native zip binaries do weird character conversions. Use PHP zipping instead.
 *
 * @param string $string  file name
 * @return string cleaned file name
 */

因此似乎雖解決上傳中文檔名問題但zip壓縮卻無法使用中文檔名,以moodle 內建pclzip也許可解決???

 以下有兩個問題待解決: 
 


下載中文檔名於IE下有問題,會轉成英文檔名,Firefox可正常下載 
無論在firefox或IE均無法壓縮與解壓縮中文檔名(備份亦然)
 

產生此問題原因分析:


IE6對於UTF-8中文檔名無法正常下載,IE7則只對zip的中文檔會產生問題其餘對office或wmv,gif,jpg不會產生問題,所以對於若是IE瀏覽器下載時將檔名轉成Big5應可解決。 
壓縮與解壓縮問題,原因在於php的basename() function對於UTF-8對中文檔名會回傳成無中文檔名或不正確之檔名(IE6與IE7不一樣,IE7較接近Frefox),改寫basename function應可解決。不知道其他php版本會不會這樣???沒試過。
 

文章最底下有一小段程式碼支持上述說法。

==================================

詳細改寫程式碼,請參閱以下說明: 

 1. 下載中文檔名於IE下有問題,Firefox可正常下載

 雖然註解lib/file.php下的這一行
//$filename = $args[count($args)-1];
send_file($pathname, $filename, $lifetime, $CFG->filteruploadedfiles, false, $forcedownload); 

可解決下載問題,但使用 //$filename = $args[count($args)-1];

則造成下一行程式call send_file(….)的filename參數為null。

trace send_file function(在lib/filelib.php檔案中)以filename無法正確取得mimetype,不知會不會造成隱含的問題?

經過簡化後測試(參閱最下面程式碼)發現應該是以@header(‘Content-Disposition: attachment; filename=’.$filename);
送出UTF-8中文檔名造成IE錯誤(與IE是否設定以UTF-8傳送URL無關)

因此做了以下修改

1. file.php不註解 $filename = $args[count($args)-1];

2. lib/filelib.php加入一小段程式碼: 

header(‘Last-Modified: ‘. gmdate(‘D, d M Y H:i:s’, $lastmodified) .’ GMT’);
if (check_browser_version()){
        $filename=iconv(“UTF-8″,”Big5”,$filename);
}
 

if ($forcedownload) {
       @header(‘Content-Disposition: attachment; filename=’.$filename);
} else {
       @header(‘Content-Disposition: inline; filename=’.$filename);    
 }

 紅色部份是加入的程式碼,check_browser_version()是在lib/moodlelib.php內的function用來檢查用戶端使用何種瀏覽器

 

2. php之basename() 內建function無法正確傳回中文檔名,造成壓縮與解壓縮問題:
於lib/moodlelib.php加一function 來取代原來的basename 直接加在程式第一個 function 前就好。
 

function file_basename($file= null) {
    if($file=== null || strlen($file)<= 0) {
        return null;
    }
   
    $file= explode(‘?’, $file);
    $file= explode(‘/’, $file[0]);
    $basename= $file[count($file)-1];
    return $basename;   
}

因此需修改的程式碼部份說明如下:

A. files/index.php修改如下

在case “paste”: 修改 
$shortfile = basename($file);->$shortfile = file_basename($file);

在case “unzip”: 修改 
$file = basename($file);->$file = file_basename($file);

 在case “listzip”: 修改 
$file = file_basename($file);->$file = file_basename($file);

 

 約825行處$fileurl改成$filesafe(fileurl為未編碼的檔名,filesafe為編碼的檔名), 則不管IE6或 IE7均能正常取得正確的檔名

else if ($icon == “zip.gif”) {
                $edittext .= “sesskey&choose=$choose\”>$strunzip “;
                //
                $edittext .= “sesskey&choose=$choose\”>$strlist “;
 

B. 修改lib/moodlelib.php

在lib/moodlelib.php

修改function zip_files(..)

//$destfilename = $path_parts[“basename”];  //The name of the zip file
    $destfilename = file_basename($destination);

//$filestozip .= escapeshellarg(basename($filetozip));
$filestozip .= escapeshellarg(file_basename($filetozip)); 

修改function unzip_file(…)

//$zipfilename = $path_parts[“basename”];  //The name of the zip file
    $zipfilename = file_basename($zipfile);

 

經過以上修改無論在Firefox, IE6 or IE7均能正常使用中文檔名了。 

 

簡化測試程式碼
——————————————–

//echo basename(“/usr/local/test/中文測試檔.zip”);

$filename=iconv(“UTF-8″,”Big5″,”中文測試檔.zip”);
//$filename=”中文測試檔.zip”;
@header(‘Content-Disposition: attachment; filename=’.$filename);
@header(‘Content-Type: application/zip’);
readfile_chunked(“中文測試檔.zip”);


//readfile_chunked 為lib/filelib.php內的function
function readfile_chunked($filename, $retbytes=true) {
    $chunksize = 1*(1024*1024); // 1MB chunks – must be less than 2MB!
    $buffer = ”;
    $cnt =0;// $handle = fopen($filename, ‘rb’);
    $handle = fopen($filename, ‘rb’);
    if ($handle === false) {
        return false;
    }
    while (!feof($handle)) {
        @set_time_limit(60*60); //reset time limit to 60 min – should be enough for 1 MB chunk
        $buffer = fread($handle, $chunksize);
        echo $buffer;
        flush();
        if ($retbytes) {
            $cnt += strlen($buffer);
        }
    }
    $status = fclose($handle);
    if ($retbytes && $status) {
        return $cnt; // return num. bytes delivered like readfile() does.
    }
    return $status;
}
?>

作者: admin

为您推荐

联系我们

联系我们

邮箱:

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部