文件名的字符串清理器


113

我正在寻找一个将清理字符串并准备用于文件名的php函数。有人知道吗?

(我会写一个,但是我担心自己会忽略一个字符!)

编辑:用于将文件保存在Windows NTFS文件系统上。


1
您能更具体一点吗:Umlauts会发生什么(删除或转换为基本字符?)特殊字符会发生什么?
Pekka 2010年

对于哪个文件系统?他们不同。见en.wikipedia.org/wiki/...
戈登

Windows :)需要15个字符。
user151841 2010年

1
我想指出,某些答案中建议的“黑名单”解决方案是不够的,因为检查每个可能的不良字符是不可行的(除了特殊字符外,还有带有重音符号和变音符号的字符,非英语/拉丁字母,控制字符等)。所以,我要说的却是一个“白名单”的做法始终是更好,和规范的字符串(由多米尼克罗杰的回答布莱尔麦克米兰的评论的建议),将允许任何字母的自然处理有口音,变音符号,等等
肖恩豆

一个使用正则表达式的好方法,请参见我制作的以下python脚本:github.com/gsscoder/normalize-fn
gsscoder

Answers:


42

不用担心忽略字符-如何使用您愿意使用的字符白名单?例如,你可以让刚刚好醇” a-z0-9_,和一段时间的单个实例(.)。这显然比大多数文件系统更具限制性,但应该可以确保您的安全。


40
不适合与Umlauts一起使用的语言。这将导致魁北克的魁北克,魁北克的杜塞尔多夫,杜塞尔多夫的杜塞尔多夫等等。
Pekka 2010年

15
是的-但就像我说的:“例如”。
多米尼克·罗杰

5
这可能是OP完全可以接受的。否则,请使用类似php.net/manual/en/class.normalizer.php的文件
Blair McMillan,2010年

3
这实际上不是要问的。op要求使用函数来清理字符串,而不是替代方法。
i.am.michiel

3
@ i.am.michiel,也许,但是鉴于OP接受了它,我认为他们认为这很有帮助。
多米尼克·罗杰

157

对Tor Valamo的解决方案进行小幅调整以解决Dominic Rodger注意到的问题,您可以使用:

// Remove anything which isn't a word, whitespace, number
// or any of the following caracters -_~,;[]().
// If you don't need to handle multi-byte characters
// you can use preg_replace rather than mb_ereg_replace
// Thanks @Łukasz Rysiak!
$file = mb_ereg_replace("([^\w\s\d\-_~,;\[\]\(\).])", '', $file);
// Remove any runs of periods (thanks falstro!)
$file = mb_ereg_replace("([\.]{2,})", '', $file);

43
我爱正则表达式迷!-_〜
AVProgrammer

2
@ iim.hlk-是的,它缺少包装括号。我现在添加了。谢谢!
肖恩·维埃拉

2
那里有一个缺陷,您应该将其分为两部分,然后进行检查..。例如.?.最终会被..。尽管自从进行过滤后,/我现在看不到如何进一步利用它,但是它说明了为什么检查..在这里无效。更好的可能是,不要替换,如果不符合条件就拒绝。
falstro 2014年

2
由于这些值在Windows文件系统上都不是非法的,为什么丢失了比您需要更多的信息?您可以将正则表达式更改为简单,[^a-z0-9_-]如果您想成为真正的限制-或仅使用生成的名称并丢弃给定名称,避免所有这些问题。:-)
肖恩·维埃拉

3
注意:是非法的。
JasonXA

49

这是您可以按照要求清理文件系统的方法

function filter_filename($name) {
    // remove illegal file system characters https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
    $name = str_replace(array_merge(
        array_map('chr', range(0, 31)),
        array('<', '>', ':', '"', '/', '\\', '|', '?', '*')
    ), '', $name);
    // maximise filename length to 255 bytes http://serverfault.com/a/9548/44086
    $ext = pathinfo($name, PATHINFO_EXTENSION);
    $name= mb_strcut(pathinfo($name, PATHINFO_FILENAME), 0, 255 - ($ext ? strlen($ext) + 1 : 0), mb_detect_encoding($name)) . ($ext ? '.' . $ext : '');
    return $name;
}

文件系统中允许其他所有内容,因此可以完美回答问题。

...,但是如果稍后在不安全的HTML上下文中使用文件名,则在文件名中使用单引号可能会很危险,'因为该文件名绝对合法:

 ' onerror= 'alert(document.cookie).jpg

成为XSS漏洞

<img src='<? echo $image ?>' />
// output:
<img src=' ' onerror= 'alert(document.cookie)' />

因此,流行的CMS软件Wordpress删除了它们,但是它们仅在进行一些更新后才涵盖所有相关字符:

$special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", "%", "+", chr(0));
// ... a few rows later are whitespaces removed as well ...
preg_replace( '/[\r\n\t -]+/', '-', $filename )

最后,他们的列表现在包括URI保留字符URL不安全字符列表中的大多数字符

当然,您可以简单地在HTML输出上对所有这些字符进行编码,但是大多数开发人员和我也都遵循成语“比对不起更好”,并提前删除它们。

所以最后我建议使用这个:

function filter_filename($filename, $beautify=true) {
    // sanitize filename
    $filename = preg_replace(
        '~
        [<>:"/\\|?*]|            # file system reserved https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
        [\x00-\x1F]|             # control characters http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
        [\x7F\xA0\xAD]|          # non-printing characters DEL, NO-BREAK SPACE, SOFT HYPHEN
        [#\[\]@!$&\'()+,;=]|     # URI reserved https://tools.ietf.org/html/rfc3986#section-2.2
        [{}^\~`]                 # URL unsafe characters https://www.ietf.org/rfc/rfc1738.txt
        ~x',
        '-', $filename);
    // avoids ".", ".." or ".hiddenFiles"
    $filename = ltrim($filename, '.-');
    // optional beautification
    if ($beautify) $filename = beautify_filename($filename);
    // maximize filename length to 255 bytes http://serverfault.com/a/9548/44086
    $ext = pathinfo($filename, PATHINFO_EXTENSION);
    $filename = mb_strcut(pathinfo($filename, PATHINFO_FILENAME), 0, 255 - ($ext ? strlen($ext) + 1 : 0), mb_detect_encoding($filename)) . ($ext ? '.' . $ext : '');
    return $filename;
}

不会导致文件系统出现问题的其他所有内容都应该是附加功能的一部分:

function beautify_filename($filename) {
    // reduce consecutive characters
    $filename = preg_replace(array(
        // "file   name.zip" becomes "file-name.zip"
        '/ +/',
        // "file___name.zip" becomes "file-name.zip"
        '/_+/',
        // "file---name.zip" becomes "file-name.zip"
        '/-+/'
    ), '-', $filename);
    $filename = preg_replace(array(
        // "file--.--.-.--name.zip" becomes "file.name.zip"
        '/-*\.-*/',
        // "file...name..zip" becomes "file.name.zip"
        '/\.{2,}/'
    ), '.', $filename);
    // lowercase for windows/unix interoperability http://support.microsoft.com/kb/100625
    $filename = mb_strtolower($filename, mb_detect_encoding($filename));
    // ".file-name.-" becomes "file-name"
    $filename = trim($filename, '.-');
    return $filename;
}

此时,如果结果为空,则需要生成一个文件名,然后可以决定是否要编码UTF-8字符。但是您不需要这样做,因为在Web托管上下文中使用的所有文件系统中都允许使用UTF-8。

唯一要做的就是使用urlencode()(希望对所有URL都使用),以便文件名საბეჭდი_მანქანა.jpg成为该URL作为您的<img src><a href>http : //www.maxrev.de/html/img/%E1%83% A1%E1%83%90%E1%83%91%E1%83%94%E1%83%AD%E1%83%93%E1%83%98_%E1%83%9B%E1%83%90% E1%83%9C%E1%83%A5%E1%83%90%E1%83%9C%E1%83%90.jpg

Stackoverflow会这样做,因此我可以像用户那样发布此链接:http :
//www.maxrev.de/html/img/საბეჭდი_მანქანა。jpg

所以这是一个完整的法律文件名和不是一个问题,因为@ SequenceDigitale.com在他的回答中提到


3
做得好。对我来说最有帮助的答案。+1

哦...该功能运行良好,但是自从一段时间以来,它开始放置在每个字符之间,例如r-u-l-e-s,我不知道为什么会发生这种情况。可以肯定的是,这不是该功能的错,而只是问-这种行为的原因是什么?编码错误?

1
哦,好吧...刚刚进行了调试,它发生在preg_replacein之后filter_filename()

删除这些评论后,它再次开始工作。

您删除了哪些评论?如果这更容易,请给我发送电子邮件:gutt.it/contact.htm
mgutt

43

使用rawurlencode()怎么样? http://www.php.net/manual/zh/function.rawurlencode.php

这是一个甚至可以清除中文字符的函数:

public static function normalizeString ($str = '')
{
    $str = strip_tags($str); 
    $str = preg_replace('/[\r\n\t ]+/', ' ', $str);
    $str = preg_replace('/[\"\*\/\:\<\>\?\'\|]+/', ' ', $str);
    $str = strtolower($str);
    $str = html_entity_decode( $str, ENT_QUOTES, "utf-8" );
    $str = htmlentities($str, ENT_QUOTES, "utf-8");
    $str = preg_replace("/(&)([a-z])([a-z]+;)/i", '$2', $str);
    $str = str_replace(' ', '-', $str);
    $str = rawurlencode($str);
    $str = str_replace('%', '-', $str);
    return $str;
}

这是解释

  1. 剥离HTML标签
  2. 删除中断/标签/回车
  3. 删除文件夹和文件名的非法字符
  4. 将字符串小写
  5. 通过将外国重音符号(例如Éàû)转换为html实体,然后删除代码并保留字母,即可将其删除。
  6. 用破折号替换空格
  7. 编码可以通过前面步骤的特殊字符,并在服务器上输入冲突文件名。例如 “中文百强网”
  8. 用破折号代替“%”,以确保在查询文件时浏览器不会重写文件的链接。

好的,某些文件名不会令人反感,但在大多数情况下它将起作用。

例如 原始名称:“საბეჭდი-და-ტიპოგრაფიული。jpg”

输出名称:“-E1-83-A1-E1-83-90-E1-83-91-E1-83-94-E1-83-AD-E1-83-93-E1-83-98--E1- 83-93-E1-83-90--E1-83-A2-E1-83-98-E1-83-9E-E1-83-9D-E1-83-92-E1-83-A0-E1-83 -90-E1-83-A4-E1-83-98-E1-83-A3-E1-83-9A-E1-83-98.jpg”

像这样比404错误更好。

希望对您有所帮助。

卡尔


1
您不会删除NULL和控制字符。0到32的ASCII应该全部从字符串中删除。
罗勒·穆萨

在文件系统中允许使用UTF-8,而在URL中允许使用UTF-8,那么为什么它会产生404错误?你需要做的唯一一件事就是将URL编码http://www.maxrev.de/html/img/საბეჭდი_მანქანა.jpghttp://www.maxrev.de/html/img/%E1%83%A1%E1%83%90%E1%83%91%E1%83%94%E1%83%AD%E1%83%93%E1%83%98_%E1%83%9B%E1%83%90%E1%83%9C%E1%83%A5%E1%83%90%E1%83%9C%E1%83%90.jpgHTML源代码,您希望您的所有网址做。
mgutt

1
其他一些要点:在删除HTML标记之前strip_tags()和之后都删除[<>]。到此为止,strip_tags()根本不需要。引号是同一点。使用解码时,没有引号了ENT_QUOTES。并且str_replace()不会删除连续的空格,然后将其strtolower()用于多字节字符串。为什么要完全转换为小写?最后,您没有抓住@BasilMusa提到的任何保留字符。我的答案中有更多详细信息:stackoverflow.com/a/42058764/318765
mgutt

爱上它了!
Yash Kumar Verma

39

解决方案1-简单有效

$file_name = preg_replace( '/[^a-z0-9]+/', '-', strtolower( $url ) );

  • strtolower()保证文件名是小写的(因为在URL中,大小写无关紧要,但在NTFS文件名中,大小写无关)
  • [^a-z0-9]+ 将确保文件名仅保留字母和数字
  • 用无效字符替换以'-'保持文件名可读

例:

URL:  http://stackoverflow.com/questions/2021624/string-sanitizer-for-filename
File: http-stackoverflow-com-questions-2021624-string-sanitizer-for-filename

解决方案2-网址很长

您要缓存URL内容,只需要具有唯一的文件名。我将使用此功能:

$file_name = md5( strtolower( $url ) )

这将创建一个固定长度的文件名。在大多数情况下,MD5哈希对于这种用法而言足够独特。

例:

URL:  https://www.amazon.com/Interstellar-Matthew-McConaughey/dp/B00TU9UFTS/ref=s9_nwrsa_gw_g318_i10_r?_encoding=UTF8&fpl=fresh&pf_rd_m=ATVPDKIKX0DER&pf_rd_s=desktop-1&pf_rd_r=BS5M1H560SMAR2JDKYX3&pf_rd_r=BS5M1H560SMAR2JDKYX3&pf_rd_t=36701&pf_rd_p=6822bacc-d4f0-466d-83a8-2c5e1d703f8e&pf_rd_p=6822bacc-d4f0-466d-83a8-2c5e1d703f8e&pf_rd_i=desktop
File: 51301f3edb513f6543779c3a5433b01c

4
也许MD5可能有问题:将带有URL的哈希值使用时要小心。虽然URL的号码skrenta.com/2007/08/md5_tutorial.html的平方根仍然大很多,但是如果您遇到冲突,则当前的网络大小会比您预期的要获得有关Britney Spears的页面大关于Bugzilla。在我们的情况下,这可能不是问题,但是对于数十亿个页面,我会选择更大的哈希算法(例如SHA 256),或者完全避免使用它。资料来源:boyter.org/2013/01/code-for-a-search-engine-in-php-part-1
adilbo,

15

好吧,tempnam()会为您做到这一点。

http://us2.php.net/manual/zh/function.tempnam.php

但这创造了一个全新的名称。

要清理现有字符串,只需限制用户可以输入的内容,并使其成为字母,数字,句点,连字符和下划线,然后使用简单的正则表达式清理即可。检查哪些字符需要转义,否则您可能得到误报。

$sanitized = preg_replace('/[^a-zA-Z0-9\-\._]/','', $filename);

13
preg_replace("[^\w\s\d\.\-_~,;:\[\]\(\]]", '', $file)

根据系统允许的内容添加/删除更多有效字符。

另外,您可以尝试创建文件,如果不好则返回错误。


5
这样可以允许通过诸如这样的文件名..,这可能会或可能不会出现问题。
Dominic Rodger 2010年

@Dom-由于它是一个固定值,因此只需单独检查即可。
Tor Valamo 2010年

10

PHP提供了将文本清除为其他格式的功能

filter.filters.sanitize

如何 :

echo filter_var(
   "Lorem Ipsum has been the industry's",FILTER_SANITIZE_URL
); 

块引用 LoremIpsumhasbeentheindustry's


1
很好,但是不能消除斜线,这可能是一个问题:目录遍历。
func0der

7

安全:将NOT“ a-zA-Z0-9_-”的每个序列替换为破折号;自己添加扩展。

$name = preg_replace('/[^a-zA-Z0-9_-]+/', '-', strtolower($name)).'.'.$extension;

1
您需要添加以“。”分隔的文件扩展名:$ name = preg_replace('/ [^ a-zA-Z0-9 _-] + /','-',strtolower($ name))。'。 。$ extension;
史密斯

6

以下表达式创建一个漂亮,干净且可用的字符串:

/[^a-z0-9\._-]+/gi

谈到今天的金融:开票今天-S-金融结算


所以文件名不能有句点或下划线,或类似的东西?
Tor Valamo 2010年

2
@Jonathan-斜体字是什么?
Dominic Rodger 2010年

@Tor,是的,对不起。更新。@Dominic,只是强调文字。
桑普森2010年

什么是吉斯?我收到“警告:preg_replace()[function.preg-replace]:未知修饰符'g'”
user151841 2010年

1
@ user151841因为preg_replace全局标志是隐式的。因此,如果正在使用preg_replace,则不需要g。当我们想控制替换次数时,preg_replace有一个limit参数。阅读preg_replace文档以获取更多信息。
rineez 2014年

6

对Sean Vieira的解决方案进行小的调整以允许单个点,您可以使用:

preg_replace("([^\w\s\d\.\-_~,;:\[\]\(\)]|[\.]{2,})", '', $file)

2

这些可能有点沉重,但是它们足够灵活,可以将任何字符串消毒为“安全”字符串 en样式的文件名或文件夹名称(或者弯曲,甚至弯曲的条和其他东西)。

1)构建完整的文件名(如果输入被完全截断,则具有备用名称):

str_file($raw_string, $word_separator, $file_extension, $fallback_name, $length);

2)或仅使用筛选器实用程序而不构建完整的文件名(严格模式true将不允许在文件名中使用[]或()):

str_file_filter($string, $separator, $strict, $length);

3)这些是这些功能:

// Returns filesystem-safe string after cleaning, filtering, and trimming input
function str_file_filter(
    $str,
    $sep = '_',
    $strict = false,
    $trim = 248) {

    $str = strip_tags(htmlspecialchars_decode(strtolower($str))); // lowercase -> decode -> strip tags
    $str = str_replace("%20", ' ', $str); // convert rogue %20s into spaces
    $str = preg_replace("/%[a-z0-9]{1,2}/i", '', $str); // remove hexy things
    $str = str_replace("&nbsp;", ' ', $str); // convert all nbsp into space
    $str = preg_replace("/&#?[a-z0-9]{2,8};/i", '', $str); // remove the other non-tag things
    $str = preg_replace("/\s+/", $sep, $str); // filter multiple spaces
    $str = preg_replace("/\.+/", '.', $str); // filter multiple periods
    $str = preg_replace("/^\.+/", '', $str); // trim leading period

    if ($strict) {
        $str = preg_replace("/([^\w\d\\" . $sep . ".])/", '', $str); // only allow words and digits
    } else {
        $str = preg_replace("/([^\w\d\\" . $sep . "\[\]\(\).])/", '', $str); // allow words, digits, [], and ()
    }

    $str = preg_replace("/\\" . $sep . "+/", $sep, $str); // filter multiple separators
    $str = substr($str, 0, $trim); // trim filename to desired length, note 255 char limit on windows

    return $str;
}


// Returns full file name including fallback and extension
function str_file(
    $str,
    $sep = '_',
    $ext = '',
    $default = '',
    $trim = 248) {

    // Run $str and/or $ext through filters to clean up strings
    $str = str_file_filter($str, $sep);
    $ext = '.' . str_file_filter($ext, '', true);

    // Default file name in case all chars are trimmed from $str, then ensure there is an id at tail
    if (empty($str) && empty($default)) {
        $str = 'no_name__' . date('Y-m-d_H-m_A') . '__' . uniqid();
    } elseif (empty($str)) {
        $str = $default;
    }

    // Return completed string
    if (!empty($ext)) {
        return $str . $ext;
    } else {
        return $str;
    }
}

因此,假设一些用户输入是: .....&lt;div&gt;&lt;/div&gt;<script></script>&amp; Weiß Göbel 中文百强网File name %20 %20 %21 %2C Décor \/. /. . z \... y \...... x ./ “This name” is & 462^^ not &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = that grrrreat -][09]()1234747) საბეჭდი-და-ტიპოგრაფიული

我们希望将其转换为更友好的名称,以使tar.gz的文件名长度为255个字符。这是一个示例用法。注意:此示例包含格式错误的tar.gz扩展名作为概念证明,在根据白名单构建字符串之后,您仍应过滤ext。

$raw_str = '.....&lt;div&gt;&lt;/div&gt;<script></script>&amp; Weiß Göbel 中文百强网File name  %20   %20 %21 %2C Décor  \/.  /. .  z \... y \...... x ./  “This name” is & 462^^ not &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = that grrrreat -][09]()1234747) საბეჭდი-და-ტიპოგრაფიული';
$fallback_str = 'generated_' . date('Y-m-d_H-m_A');
$bad_extension = '....t&+++a()r.gz[]';

echo str_file($raw_str, '_', $bad_extension, $fallback_str);

输出为: _wei_gbel_file_name_dcor_._._._z_._y_._x_._this_name_is_462_not_that_grrrreat_][09]()1234747)_.tar.gz

您可以在这里玩:https : //3v4l.org/iSgi8

或要点:https : //gist.github.com/dhaupin/b109d3a8464239b7754a

编辑: 更新脚本过滤器&nbsp;代替空间,更新3v4l链接


1

我今天所知道的最好的是静态方法Strings :: webalize Nette框架中的。

顺便说一句,这会将所有变音符号转换成它们的基本符号。š=> sü=> uß=> ss等

对于文件名,您必须添加点“。” 允许的字符参数。

/**
 * Converts to ASCII.
 * @param  string  UTF-8 encoding
 * @return string  ASCII
 */
public static function toAscii($s)
{
    static $transliterator = NULL;
    if ($transliterator === NULL && class_exists('Transliterator', FALSE)) {
        $transliterator = \Transliterator::create('Any-Latin; Latin-ASCII');
    }

    $s = preg_replace('#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{2FF}\x{370}-\x{10FFFF}]#u', '', $s);
    $s = strtr($s, '`\'"^~?', "\x01\x02\x03\x04\x05\x06");
    $s = str_replace(
        array("\xE2\x80\x9E", "\xE2\x80\x9C", "\xE2\x80\x9D", "\xE2\x80\x9A", "\xE2\x80\x98", "\xE2\x80\x99", "\xC2\xB0"),
        array("\x03", "\x03", "\x03", "\x02", "\x02", "\x02", "\x04"), $s
    );
    if ($transliterator !== NULL) {
        $s = $transliterator->transliterate($s);
    }
    if (ICONV_IMPL === 'glibc') {
        $s = str_replace(
            array("\xC2\xBB", "\xC2\xAB", "\xE2\x80\xA6", "\xE2\x84\xA2", "\xC2\xA9", "\xC2\xAE"),
            array('>>', '<<', '...', 'TM', '(c)', '(R)'), $s
        );
        $s = @iconv('UTF-8', 'WINDOWS-1250//TRANSLIT//IGNORE', $s); // intentionally @
        $s = strtr($s, "\xa5\xa3\xbc\x8c\xa7\x8a\xaa\x8d\x8f\x8e\xaf\xb9\xb3\xbe\x9c\x9a\xba\x9d\x9f\x9e"
            . "\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3"
            . "\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8"
            . "\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xfe"
            . "\x96\xa0\x8b\x97\x9b\xa6\xad\xb7",
            'ALLSSSSTZZZallssstzzzRAAAALCCCEEEEIIDDNNOOOOxRUUUUYTsraaaalccceeeeiiddnnooooruuuuyt- <->|-.');
        $s = preg_replace('#[^\x00-\x7F]++#', '', $s);
    } else {
        $s = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $s); // intentionally @
    }
    $s = str_replace(array('`', "'", '"', '^', '~', '?'), '', $s);
    return strtr($s, "\x01\x02\x03\x04\x05\x06", '`\'"^~?');
}


/**
 * Converts to web safe characters [a-z0-9-] text.
 * @param  string  UTF-8 encoding
 * @param  string  allowed characters
 * @param  bool
 * @return string
 */
public static function webalize($s, $charlist = NULL, $lower = TRUE)
{
    $s = self::toAscii($s);
    if ($lower) {
        $s = strtolower($s);
    }
    $s = preg_replace('#[^a-z0-9' . preg_quote($charlist, '#') . ']+#i', '-', $s);
    $s = trim($s, '-');
    return $s;
}

为什么要替换变音符号?urlencode()在将文件名用作src或之前只需使用即可href。目前唯一使用的UTF-8出现问题的文件系统是FATx(由XBOX使用):en.wikipedia.org/wiki/Comparison_of_file_systems#Limits而且我不认为Web服务器会使用此文件系统
mgutt

1

似乎所有这些都取决于问题,是否有可能创建一个可用于入侵服务器的文件名(或造成某种其他破坏)。如果没有,那么似乎最简单的答案是尝试在最终使用该文件的地方创建文件(因为毫无疑问,这将是首选的操作系统)。让操作系统对其进行整理。如果有投诉,请将该投诉作为验证错误转回给用户。

这具有可靠移植的额外好处,因为如果该操作系统的文件名格式不正确,所有(我很确定)操作系统都会抱怨。

如果可以做到的邪恶事情的文件名,也许是可以驻地操作系统上测试文件名之前被应用措施-措施不是文件名的一个完整的“卫生”那么复杂。


0

单程

$bad='/[\/:*?"<>|]/';
$string = 'fi?le*';

function sanitize($str,$pat)
{
    return preg_replace($pat,"",$str);

}
echo sanitize($string,$bad);

不可打印字符呢?在这种情况下,使用白名单方法比黑名单方法更好。基本上只允许可打印的ASCII文件名,当然不包括特殊字母。但是对于非英语语言环境,这是另一个问题。
TheRealChx101 '18

0

/并且..用户提供的文件名可能有害。因此,您应该通过以下方法消除这些问题:

$fname = str_replace('..', '', $fname);
$fname = str_replace('/',  '', $fname);

这还不够!例如,文件名“ ./.name”仍会脱离当前目录。(在此处删除..不会执行任何操作,但是删除/会将./。变成..从而脱离目标目录。)
cemper93 2015年

3
@ cemper93不,这个答案只会把字符串变成..name不会破任何东西的字符串。删除所有路径分隔符应足以防止任何目录遍历。(从..技术上讲,删除是不必要的。)
cdhowie

@cdhowie是的,但是文件名./.变为..。最后,这个答案错过了所有其他文件系统保留的字符,例如NULL。我的答案中的更多信息:stackoverflow.com/a/42058764/318765
mgutt

-4

$ fname = str_replace('/','',$ fname);

由于用户可能使用斜杠分隔两个单词,因此最好用破折号代替NULL代替


在哪里说他将用NULL代替?同样,这不能处理所有特殊字符。
Travis Pessetto

是的-还有其他特殊字符也需要处理。无论如何,str_replace并不是最好的出价。
Martin Kovachev 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.