programing

PHP의 고유하고 임시 파일 이름?

sourcetip 2021. 1. 16. 11:17
반응형

PHP의 고유하고 임시 파일 이름?


일부 파일을 PDF로 변환 한 다음 이메일에 첨부해야합니다. 나는 이메일쪽에 Pear Mail을 사용하고 있으며 괜찮습니다 (대부분-여전히 몇 가지 문제를 해결하고 있음).하지만 이것의 일부로 임시 파일을 만들어야합니다. 이제 tempnam () 함수를 사용할 수 있지만 파일 시스템에 파일을 생성하는 것처럼 들립니다.

동일한 사용자가 스크립트를 두 번 이상 호출하는 동일한 스크립트를 실행하는 다른 사람과 충돌하지 않는 임시 파일 시스템의 이름 ( sys_get_temp_dir () 사용)을 원합니다 .

제안?


나는 과거에 uniqid ()를 사용하여 고유 한 파일 이름을 생성했지만 실제로 파일을 생성하지는 않았습니다.

$filename = uniqid(rand(), true) . '.pdf';

첫 번째 매개 변수는 원하는대로 지정할 수 있지만 여기서는 rand ()를 사용하여 좀 더 무작위로 만들었습니다. 집합 접두사를 사용하면 시스템의 다른 임시 파일과의 충돌을 더욱 방지 할 수 있습니다.

$filename = uniqid('MyApp', true) . '.pdf';

거기에서 파일을 만듭니다. 다른 모든 것이 실패하면 while 루프에 넣고 작동하는 것을 얻을 때까지 계속 생성하십시오.

while (true) {
 $filename = uniqid('MyApp', true) . '.pdf';
 if (!file_exists(sys_get_temp_dir() . $filename)) break;
}

진지하게, tempnam ()을 사용하십시오. 예, 이렇게하면 파일이 생성되지만 이는 시스템의 다른 프로세스가 파일 이름을 "도용"하여 프로세스가 원하지 않는 파일을 덮어 쓰는 것을 방지하기 위해 고안된 매우 의도적 인 보안 조치입니다.

즉, 다음 순서를 고려하십시오.

  • 임의의 이름을 생성합니다.
  • 파일 시스템이 존재하지 않는지 확인합니다. 그렇다면 이전 단계를 반복하십시오.
  • 또 다른 사악한 프로세스는 Mr Evil이 실수로 덮어 쓰도록 요청한 파일에 대한 하드 링크와 동일한 이름의 파일을 만듭니다.
  • 쓰기 모드에서 기존 파일을 여는 것이 아니라 파일을 만들고 있다고 생각하고 파일을 열고 쓰기 시작합니다.
  • 중요한 것을 덮어 썼습니다.

PHP의 tempnam ()은 실제로 시스템의 mkstemp를 내부에서 호출합니다 (리눅스를위한 것입니다 ... 다른 OS를 "모범 사례"함수로 대체). 다음과 같은 프로세스를 거칩니다.

  • 파일 이름 선택
  • 다른 사람이 소유하지 않은 파일을 제거하지 못하도록하는 디렉토리 내부에 제한적인 권한으로 파일을 만듭니다 (이것이 고정 비트가 / var / tmp 및 / tmp에서 수행하는 작업입니다).
  • 생성 된 파일에 여전히 제한적인 권한이 있는지 확인합니다.
  • 위의 방법 중 하나라도 실패하면 다른 이름으로 다시 시도하십시오.
  • 생성 된 파일 이름을 반환합니다.

이제 이러한 모든 작업을 직접 수행 할 수 있지만 "적절한 기능"이 보안 임시 파일을 생성하는 데 필요한 모든 작업을 수행하고 거의 항상 빈 파일을 생성해야하는 이유입니다.

예외 :

  • 프로세스 만 파일을 생성 / 삭제할 수있는 디렉토리에 임시 파일을 생성합니다.
  • 프로세스 만 파일을 생성 / 삭제할 수 있는 임의로 생성 된 임시 디렉토리 를 만듭니다.

고유 한 파일 이름을 생성하기 위해 날짜 및 시간의 일부를 사용할 수 있습니다. 이렇게하면 두 번 이상 호출 될 때 중복되지 않습니다.


파일 이름에 uuid를 사용하는 것이 좋습니다. uniqid 기능을 고려하십시오. http://php.net/uniqid


@Lusid최대 실행 시간의 장애 조치 (failover) 대한 응답을 기반으로하는 또 다른 대안 :

//////////// Max exectution time of 10 seconds.
$maxExecTime = time() + 10; 
$isUnique = false;

while (time() !== $maxExecTime) {
    //////////// Unique file name
    $uniqueFileName = uniqid(mt_rand(), true) . '.pdf';
    if (!file_exists(sys_get_temp_dir() . $uniqueFileName)){
        $isUnique = true;
        break;
    }
}

if($isUnique){
    //////////// Save your file with your unique name
}else{
    //////////// Time limit was exceeded without finding a unique name
}

노트 :

나는 첫 번째 기능을 사용 하고 두 번째 ( ) 보다 빠르기 때문에 mt_rand대신 사용하는 것을 선호합니다 .randMersenne Twister algorithmLCG


더 많은 정보:


http://www.php.net/tempnam PHP 기능 사용을 권장합니다 .

$file=tempnam('tmpdownload', 'Ergebnis_'.date(Y.m.d).'_').'.pdf';
echo $file;
/var/www/html/tmpdownload/Ergebnis_20071004_Xbn6PY.pdf

또는 http://www.php.net/tmpfile

<?php
$temp = tmpfile();
fwrite($temp, "writing to tempfile");
fseek($temp, 0);
echo fread($temp, 1024);
fclose($temp); // this removes the file
?>

내 생각은 재귀 함수를 사용하여 파일 이름이 있는지 확인하고 존재하는 경우 다음 정수로 반복하는 것입니다.

function check_revision($filename, $rev){
    $new_filename = $filename."-".$rev.".csv";
    if(file_exists($new_filename)){
        $new_filename = check_revision($filename, $rev++);
    }
    return $new_filename;
}

$revision = 1;
$filename = "whatever";
$filename = check_revision($filename, $revision);

사용자 ID와 함께 Unix 타임 스탬프를 더 잘 사용하십시오.

$filename='file_'.time().'_'.$id.'.jepg';

function gen_filename($dir) {
    if (!@is_dir($dir)) {
        @mkdir($dir, 0777, true);
    }
    $filename = uniqid('MyApp.', true).".pdf";
    if (@is_file($dir."/".$filename)) {
        return $this->gen_filename($dir);
    }
    return $filename;
}

참조 URL : https://stackoverflow.com/questions/460164/unique-and-temporary-file-names-in-php

반응형