문자열을 삭제하고 파일 이름에 사용할 수 있도록 준비하는 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;
}
여기에 설명이 있습니다
- HTML 태그 제거
- 브레이크 / 탭 / 반환 캐리지 제거
- 폴더 및 파일 이름에 대한 잘못된 문자 제거
- 문자열을 소문자로 입력
- Éàû와 같은 외국 악센트를 html 엔터티로 변환하여 제거한 다음 코드를 제거하고 문자를 유지합니다.
- 공백을 대시로 바꾸기
- 이전 단계를 통과 할 수있는 특수 문자를 인코딩하고 서버에서 충돌 파일 이름을 입력합니다. 전의. “中文 百强 网”
- 파일을 쿼리 할 때 브라우저가 파일 링크를 다시 쓰지 않도록 “%”를 대시로 바꿉니다.
좋아, 일부 파일 이름은 릴리스되지 않지만 대부분의 경우 작동합니다.
전의. 원래 이름 : “საბეჭდი-და-ტიპოგრაფიული. 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)
시스템에 허용되는 항목에 따라 더 많은 유효한 문자를 추가 / 제거합니다.
또는 파일 생성을 시도한 다음 문제가있는 경우 오류를 반환 할 수 있습니다.