让wp-downloadmanager支持中文文件名

某日在老外一个博客上逛,发现它上面的东东下载方式有点不同,于是查看了下它页面的HTML源代码,发现疑似物:wp-downloadmanager 。GOOGLE了下,还真找到这个东东了。用过一段时间后,发现它有一个BUG,就是没有考虑中文这样的非拉丁字符,导致上传的纯中文名称的附件名称只剩下从“.”开始后面的东东了,比如我通过它上传“ 中文.test ” 这个文件,最终的结果是这个文件在服务器上的名称变成了“ .test “ 。这样就会出问题,因为只要是全中文名的文件一上传上去后名称全部变成一个模样啦。

于是我从它的源代码入手,看它是怎么处理上传的。它处理上传的文件是:download-add.php ,从这个文件可以看到它处理从本地上传文件的代码块为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
case 1:

                    if($_FILES['file_upload']['size'] > get_max_upload_size()) {

                        $text = '<font color="red">'.sprintf(__('File Size Too Large. Maximum Size Is %s', 'wp-downloadmanager'), format_filesize(get_max_upload_size())).'</font>';

                        break;

                    } else {

                        if(is_uploaded_file($_FILES['file_upload']['tmp_name'])) {

                            if($_POST['file_upload_to'] == '/') {

                                $file_upload_to = '/';

                            } else {

                                $file_upload_to = $_POST['file_upload_to'].'/';

                            }

                            if(move_uploaded_file($_FILES['file_upload']['tmp_name'], $file_path.$file_upload_to.basename($_FILES['file_upload']['name']))) {

                                $file = $file_upload_to.basename($_FILES['file_upload']['name']);

                                $file = download_rename_file($file_path, $file);
                               

                                $file_size = filesize($file_path.$file);   

                            } else {

                                $text = '<font color="red">'.__('Error In Uploading File', 'wp-downloadmanager').'</font>';

                                break;

                            }

                        } else {

                            $text = '<font color="red">'.__('Error In Uploading File', 'wp-downloadmanager').'</font>';

                            break;

                        }

                    }

                    break;

首先引起我怀疑的是download_rename_file这个函数,这个函数的定义是在wp-downloadmanager.php文件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
### Function: Rename File To Ensure (Credits: imvain2)
function download_rename_file($file_path, $file) {
    $rename = false;
    $file_old = $file;
    $file = str_replace(' ', '_', $file);
    $file = preg_replace('/[^A-Za-z0-9\-._\/]/', '', $file);
    if($file != $file_old) {
        $rename = rename($file_path.$file_old, $file_path.$file);
    }
    if($rename) {
        return $file;
    } else {
        return $file_old;
    }
}

从上可看出这个函数先是把文件名中的空格换成了下划线,这不要紧,关键是下面这一句:

1
$file = preg_replace('/[^A-Za-z0-9\-._\/]/', '', $file);

它把文件名中除去大小写字母、数字、连接符号、点号、下划线和斜杠之外的所有字符都通通毫不留情地给替换为空了,这样中文文件名的中的中文字符就这样消失啦。
于是修改了一这个函数中的正则,让它对中文手下留情:

1
$file = preg_replace("/[^A-Za-z0-9\-._\/\x7f-\xff]/", '', $file);

本以为这样以后就完事啦,谁知这样以后问题依旧存在。我想问题肯定不是单单出在这,肯定还有别的函数对中文字符“先下杀手”了。于是继续看代码,在上面给出的download-add.php 中代码块的

1
$file = download_rename_file($file_path, $file);

这一行上面dump :

1
2
3
4
5
var_dump($file);
echo '<br>';
var_dump($_FILES['file_upload']['name']);
echo '<br>';
var_dump(basename($_FILES['file_upload']['name']));

再在

1
$file = download_rename_file($file_path, $file);

这行下面下“断点”:

1
die($file);

这样保存后,再去后台通过wp-downloadmanager上传一个中文名的文件,发现中文名是被basename这个php内置函数给扼杀了。
为了进一步证实我观点的正确性,于是写了个测试文件: zw.php
内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
function getFileBaseName($file_name)

{
if(eregi('/',$file_name)){
$baseDir=dirname($file_name);
$basename=str_replace($baseDir,'',$file_name);
$basename=str_replace('/','',$basename);
}
else {
$basename=$file_name;

}

return $basename;

}

  //eg: $_GET['a']='/dd/ww/cc/中文.test';

$a=preg_replace("/[^A-Za-z0-9\-._\/\x7f-\xff]/", '', $_GET['a']);
echo $a.'<br>';
$b=basename($_GET['a']);    
echo $b.'<br>';   // will print '.test'
$c=getFileBaseName($_GET['a']);  
echo $c;  //     中文.test
?>

提交zw.php?a=/dd/ww/cc/中文.test时,输出:

1
2
3
/dd/ww/cc/中文.test
.test
中文.test

上述测试证实了我的观点的正确性,于是在wp-downloadmanager.php中增加自定义函数 getFileBaseName用来取代basename :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function getFileBaseName($file_name)

{
if(eregi('/',$file_name)){
$baseDir=dirname($file_name);
$basename=str_replace($baseDir,'',$file_name);
$basename=str_replace('/','',$basename);
}
else {
$basename=$file_name;

}

return $basename;

}

再把插件中凡是用到basename函数的地方全部换成getFileBaseName 。这样以后再测试,发现问题得到解决了。

喜欢这篇文章吗?

请订阅本站 RSS feed填写您的邮件地址,订阅我们的精彩内容:

随机日志

回复 (7)

  1. 何苦呢  / 回复

    如何外国的主机支持中文名称的文件 还不乱码才好呢

  2. 香肠Ⅰ号  / 回复

    :grin: 领教,先试试看!

  3. ③秋之流☆  / 回复

    刚才看来访信息,发现有人搜这个插件去到我的博客,心血来潮,我也搜了一下,来到了你这里.

    以前我也装过这个插件,不过后来发现在后台的时候IE会有报错(前台不记得有没有了),貌似还会影响编辑器的一些按钮,我不懂怎么解决,就停用了..

    • 荒野无灯  / 回复

      其实不会的,如果报错的话,基本上可以确定你是用古老的IE6浏览器,经我测试,在目前主流浏览器下都没有问题。 :grin:
      我这里折腾出了一个升级版: 《wordpress下载管理插件Hacklog-downloadmanager》
      目前我在用这个。 :mrgreen:

  4. 嘉林  / 回复

    好,支持,辛苦了。
    我现在不会用这个插件,文件上传了,插件设置里也添加了,就是不知道怎么在日志里插入下载。

    • 荒野无灯  / 回复

      @嘉林, 在代码编辑器里,点那个 download按钮,然后会弹出框来,你填入一个id,这个id就是你上传后文件的id,在后台可以看到文件ID的 :mrgreen:

发表评论 修改评论取消编辑

允许使用的标签 - 您可以在评论中使用如下的 HTML 标签以及属性。

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 :wink:  :-|  :-x  :twisted:  :)  8-O  :(  :roll:  :-P  :oops:  :-o  :mrgreen:  :lol:  :idea:  :-D  :evil:  :cry:  8)  :arrow:  :-?  :?:  :!:

引用通告 (0)

› 尚无引用通告。

开灯