[php] 파일 이름에 대한 문자열 새니 타이 저

문자열을 삭제하고 파일 이름에 사용할 수 있도록 준비하는 PHP 함수를 찾고 있습니다. 누구나 편리한 것을 알고 있습니까?

(하나 쓸 수 있지만 캐릭터를 놓칠 까 봐 걱정!)

편집 : Windows NTFS 파일 시스템에 파일을 저장합니다.



답변

캐릭터를 간과하는 것에 대해 걱정하는 대신-기꺼이 사용되는 캐릭터의 화이트리스트를 사용하는 것은 어떻습니까? 예를 들어, 당신은 그냥 좋은 팔자을 허용 할 수있는 a-z, 0-9, _, 및 기간의 단일 인스턴스 ( .). 이는 대부분의 파일 시스템보다 분명히 더 제한적이지만 안전을 유지해야합니다.


답변

Dominic Rodger가 발견 한 문제를 해결하기 위해 Tor Valamo의 솔루션을 약간 조정하면 다음 사용할 있습니다.

// 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);


답변

요청에 따라 파일 시스템을 삭제하는 방법입니다.

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 문자를 인코딩할지 여부를 결정할 수 있습니다. 그러나 웹 호스팅 컨텍스트에서 사용되는 모든 파일 시스템에서 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 .


답변

rawurlencode () 사용은 어떻습니까?
http://www.php.net/manual/en/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- 간단하고 효과적

$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

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


답변

음, tempnam ()이 당신을 위해 그것을 할 것입니다.

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

그러나 그것은 완전히 새로운 이름을 만듭니다.

기존 문자열을 삭제하려면 사용자가 입력 할 수있는 항목을 제한하고 문자, 숫자, 마침표, 하이픈 및 밑줄로 만든 다음 간단한 정규식으로 삭제하면됩니다. 이스케이프해야하는 문자를 확인하십시오. 그렇지 않으면 오 탐지가 발생할 수 있습니다.

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


답변

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

시스템에 허용되는 항목에 따라 더 많은 유효한 문자를 추가 / 제거합니다.

또는 파일 생성을 시도한 다음 문제가있는 경우 오류를 반환 할 수 있습니다.