作者hyderai (飘)
看板PHP
标题Re: [请益] Windows下读许功盖档名的档案
时间Fri Sep 21 23:51:29 2012
自问自答 整理一下目前的看法 有错还请麻烦指正
首先 Google 找到大部分关於许功盖的问题 通常是为了解决将Big5编码的许功盖字串
存入 DB 时会遇到的问题 因为这些字串包含\字元
而\通常在程式中通常有跳脱字元的义涵
所以通常用addslashes函式处理过後 再存入DB中
要使用时再从DB取出 使用stripslashes函式 来显示到网页上
不过实际上只要上传网页、存入的中文字串以及使用的DB都使用utf-8编码
就可以避掉这个问题 所以在此例上传档案的情况 只要上传的 php 网页使用utf-8编码
基本上$_FILES['userfile']['name'] 就会是utf-8编码
如果想将档名存入 DB 直接使用这个变数就可以了
问题在於如果要存上传档案到Server上 而Server又是Windows (Big5)的话
因为只能存big5档名 而不能存utf-8档名 所以一般直觉会使用下面做法:
$upload_dir = "upload/";
$big5_fn = mb_convert_encoding($_FILES['userfile']['name'],
"utf-8", "big5"); //将 utf8 档名转成 Big5 档名
move_uploaded_file($_FILES['userfile']['tmp_name'] ,
($upload_dir . $big5_fn) ); //移到上传资料夹
然後就是恶梦的开始
因为先前提过的许功盖字串问题 这些字串内包含\字元
所以使用像是is_file、readfile这些函式时会发生问题
猜测可能是因为这些函式接受路径档名
而这些函式内部又没对许功盖的情况做处理
所以对这些函式 "upload\许功盖.txt" 看起来会是"upload\?\?\.txt"
所以就出问题了
目前找到的作法 就是不要存中文档名 另外使用其他英文数字来当档名
可想而知 就得存对应档名的资讯 ex. 许功盖.txt <=> abc123.txt
如果不想存?
用urlencode()编码处理 避掉许功盖问题後再存?
这里又会衍生一个问题 Windows 档名有260个字元限制
用urlencode() 是会爆的做法
目前看到有的人使用英数档名 然後多使用md5()来编码 压缩档名到32个字元
避免长度超过 可以参考看看
不过得记得 md5() 是不可逆的 (如果不讨论破解之类的)
※ 引述《hyderai (飘)》之铭言:
: 因为环境是Windows server 所以不得不处理Big5 许功盖的问题
: 目前要读取使用者上传到网站上的档案 因为Server是Windows
: 所以档名都是big5编码 假设档案就是上传到upload资料夹下
: 在读取upload资料夹下的档案时 如果遇到档名是许功盖的情形
: (ex. 许功盖.txt) 使用is_file, readfile之类的函式 都没办法正常判断及读取
: 不知道有没有什麽解决方法?
: <?php
: header('Content-type: text/html; charset=utf-8');
: $a = array();
: $a = scandir("upload/");
: foreach($a as $value){
: echo "档案名称:". $value . "<br />";
: if(is_file("upload/" . $value)){
: echo "档案内容:<br />";
: echo "略<br />\n";
: }
: else{
: echo "非档案:<br />"; //$value 是许功盖.txt时会判断成非档案
: }
: }
: ?>
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 114.34.162.25
1F:→ MOONRAKER:md5是单向杂凑函数又不是对称加密,当然不可逆。 09/22 03:11
2F:→ liaosankai:=.=疑?原PO有说md5()可逆吗?1F感觉回答的很严肃 09/22 03:43
3F:→ kerash:最後一句是疑问,一楼没甚麽回答有问题的状况 09/22 09:51
4F:→ Johnnyvip:我个人是用英数取个随机的档案名称 再用资料库对照 09/22 11:53
5F:→ Johnnyvip:读取用资料库搭配header 09/22 11:56
6F:→ Johnnyvip:不建议在server上用中文档名 09/22 12:01
7F:→ Johnnyvip:不管是在windows或是linux上 09/22 12:03
8F:→ Johnnyvip:而且尽量用windows和linux都能够使用的方法 09/22 12:05
9F:→ Johnnyvip:不然程式要换os执行的话 会需要另外修改 09/22 12:07
10F:→ alpe:档名用md5放, 实际档名另存这样作比较简单. 09/24 01:08
11F:推 gname:推楼上的方法,我也这麽做,只是总觉得可能会有看不见的bug 囧 09/24 08:38