2011-08-30 2 views
25

PHP가있는 배치에서 처리해야하는 파일이있는 디렉토리가 있습니다. 파일은 FTP를 통해 서버에 복사됩니다. 파일 중 일부는 크기가 커서 복사하는 데 오랜 시간이 걸립니다. 파일이 아직 전송 중인지 PHP로 결정할 수 있습니까? (따라서 파일 처리를 건너 뛸 수 있으므로 다음 번 배치 프로세스에서 처리 할 수 ​​있습니까?)파일이 여전히 ftp를 통해 전송되는지 확인하는 방법

파일 크기를 확인하고 잠시 기다렸다가 파일 크기가 다른지 확인하십시오. 전송이 잠시 멈추는 약간의 기회가 있기 때문에 이것은 방수가되지 않습니다 ...

+1

흠, 흥미로운 질문 참으로 filemtime로 할 수있는 같은! +1 –

+0

[ftp_nb_put] (http://nl3.php.net/manual/en/function.ftp-nb-put.php)을 사용할 수 있습니다 (문서에 while 루프가있는 예 참조). –

+1

리눅스에서 exec를 사용하여 'lsof | grep filename ' –

답변

5

우리 서버 관리자는 현재 전송중인 파일을 출력하는 ftpwho를 제안했습니다.

http://www.castaglia.org/proftpd/doc/ftpwho.html

그래서 해결책은 디렉토리에 파일이 전송되고 있는지 확인하기 ftpwho 명령의 출력을 구문 분석하는 것입니다.

9

가장 안전한 방법 중 하나는 임시 이름으로 파일을 업로드 한 다음 전송이 완료되었습니다. 프로그램에서는 임시 이름을 가진 파일을 건너 뛰어야합니다 (간단한 확장은 정상적으로 작동합니다.) 분명히 클라이언트 (업 로더)가 협력해야하기 때문에 이상적이지 않습니다.

은 파일 크기가 정확성과 안전하지 않은 폴링 기반으로

아무것도 [이것은 또한 당신이 필요하면 당신은 주어진 시간 기간 이후에 실패 (부분) 전송을 삭제합니다. 수 있습니다].

다른 구성표 (업 로더도 협력해야 함)는 파일의 해시와 크기를 먼저 업로드 한 다음 실제 파일을 업로드하는 과정을 수반 할 수 있습니다. 이를 통해 전송이 완료되면 일관성이 있는지 여부를 알 수 있습니다. (이 아이디어를 둘러싼 변형이 많이 있습니다.)

클라이언트와 협력 할 필요가없는 것은 파일이 다른 프로세스에서 열려 있는지 여부를 확인하는 것입니다. (당신이하는 일은 OS 의존적입니다 - 이것을 수행하는 PHP 내장 함수를 모른다. lsof 및/또는 fuser은 다양한 Unix 유형 플랫폼에서 사용할 수 있지만 Windows에는 이에 대한 API가 있습니다.) 다른 프로세스에 파일이 열리면 아직 완료되지 않은 가능성이 있습니다.

업로드를 다시 시작/다시 시작하도록 허용하거나 FTP 서버 소프트웨어가 YMMV와 같이 전체 전송 기간 동안 파일을 열어 두지 않으면이 마지막 접근 방법은 바보가 될 수 없습니다.

+1

전송은 ftp를 통해 사용자에 의해 수행되고 PHP에 의해 시작되지 않습니다. 사용자가 파일을 전송할 때 파일의 이름을 바꿔야하는 것을 원하지 않습니다. – murze

+1

클라이언트에서 아무 것도 요구하지 않는 한 가지 방법으로 내 대답을 편집했습니다. 그것은 절대 안전하지 않습니다. (나는 평범한 FTP가 있다고는 생각하지 않는다.) – Mat

+1

참고 :'lsof'와'fuser'는'root'로 실행되어 다른 사용자들에 대해 알려줄 필요가 있습니다. 또한 파일이 NFS fs에 있다면'lsof' 또는'fuser' 명령을 실행하고있는 컴퓨터가 아니라 다른 컴퓨터에서 파일을 쓰고 있다는 것을 알려주지 않습니다. –

4

일부 FTP 서버는 특정 이벤트가 발생할 때 명령을 실행하도록 허용합니다. 따라서 FTP 서버에서 허용하는 경우 간단한 시그널링 구성표를 작성하여 파일이 다소 성공적으로 업로드되었음을 애플리케이션에 알릴 수 있습니다 (사용자가 파일을 업로드할지 여부를 모르기 때문에 더 많거나 적음). 완전히 또는 부분적으로). 신호 방식은 "uploaded_file_name.ext.complete"파일 작성과 같이 간단 할 수 있으며 확장명이 ".complete"인 파일의 존재를 모니터합니다.

이제 파일을 쓰기 위해 열 수 있는지 확인할 수 있습니다. 대부분의 FTP 서버는 파일을 업로드 할 때이 작업을 허용하지 않습니다.

매트가 언급 한 또 다른 접근법은 시스템 특정 기술을 사용하여 파일이 다른 프로세스에서 열렸는지 확인하는 것입니다.

2

확인하는 가장 좋은 방법은 flock을 사용하여 파일에 단독 잠금을 시도하는 것입니다. sftp/ftp 프로세스는 fopen 라이브러리를 사용합니다.

// try and get exclusive lock on file 
$fp = fopen($pathname, "r+"); 

if (flock($fp, LOCK_EX)) { // acquire an exclusive lock 
    flock($fp, LOCK_UN); // release the lock 
fclose($fp); 
} 
else { 
    error_log("Failed to get exclusive lock on $pathname. File may be still uploading."); 
} 
+0

이것은 업로드하지 않아도 대부분의 파일에 대해 else 문을 트리거합니다. – Rapti

+0

FTP 서버가 파일 전송을 잠그지 않습니다. 따라서이 테스트는 잘못되었습니다. – artoodetoo

+0

나에게 맞는 것 같다 .... 자물쇠를 얻을 수 없다면 .... 파일은 여전히 ​​..... 그가 찾고있는 것 같다 ... upvote. –

0

그것의 정말 좋은하지 트릭,하지만 간단 :-)의, 유

$result = false; 
$tryies = 5; 
if (file_exists($filepath)) { 
    for ($i=0; $i < $tryies; $i++) { 
     sleep(1); 
     $filesize[] = filesize($filepath); 
    } 
    $filesize = array_unique($filesize); 
    if (count($filesize) == 1) { 
     $result = true; 
    } else { 
     $result = false; 
    } 
} 

return $result; 
관련 문제