2011-12-28 4 views
1

이 함수는 결과 세트 (파일 이름)를 반환하고 사용자가 데스크탑에 저장하도록 압축합니다.천 개 이상의 파일을 압축 할 수 없습니다.

function getFiles() { 
error_reporting(E_ALL); 
ini_set("display_errors", 1); 
ini_set('zlib.output_compression', 'Off'); 
$result = null; 
$ZIPresult = null; 
$cleanup = null; 
$output = null; 
$fileName = 'SearchResult.zip'; 
//remove old zip if any 
$cleanup = shell_exec("/bin/rm -f SearchResult.zip"); 
error_log("SHELL OUTPUT=>" . $cleanup, 0); 
//test 
if (empty($_POST['DBSite'])) { return null; } 
$mydir = MYDIR; // set from the CONSTANT 
$dir = opendir($mydir); 
$DBSite = $_POST['DBSite']; 
$getfilename = mysql_query("select /*! SQL_CACHE */ filename from automation_search where site='" . $DBSite . "'") or die(mysql_error()); 
while ($row = mysql_fetch_array($getfilename)) { 
$filename = $row['filename']; 
$result .= '<tr><td><a href="' . basename($mydir) . '/' . $filename . '" target="_blank">' . $filename . '</a></td></tr>'; 
$ZIPresult .= basename($mydir) . '/' . escapeshellarg($filename).' '; 
} 

if ($result) { 
$result = "<table><tbody><tr><td>Search Results.</td></tr> $result</table>"; 
$output = shell_exec("/usr/bin/zip -R SearchResult.zip ". $ZIPresult ." 2>&1 "); 
error_log("SHELL OUTPUT=>" . $output, 0); 
error_log("ZIP FILENAME=>" . $fileName, 0); 

if (file_exists($fileName)) { 
//header for forced download 
    header('Content-Description: File Transfer'); 
    header('Content-Type: application/octet-stream'); 
    header('Content-Disposition: attachment; filename='.basename($fileName)); 
    header('Content-Transfer-Encoding: binary'); 
    header('Expires: 0'); 
    header('Cache-Control: must-revalidate'); 
    header('Pragma: public'); 
    header('Content-Length: ' . filesize($fileName)); 
    ob_clean(); 
    flush(); 
    readfile($fileName); 
    exit; 
    } 
} 

return $result; 
} 

약 1,000 개 미만의 파일 (약)에서만 작동합니다. 마치 메모리 한도에 도달하고 파일 목록이 화면에 출력되는 것과 같습니다.

오류는 Error.log에 있습니다. ZIP 파일은 내가

shell_exec("/usr/bin/zip -R SearchResult.zip ". $ZIPresult ." 2>&1 ");

차이에

shell_exec("/usr/bin/zip SearchResult.zip ". $ZIPresult ." ");에서 내 우편 명령 줄을 변경 시도 생성되지 않습니다. 내가 뭘 놓치고 있니?

+0

SQL 인수도 함께 이스케이프 처리하십시오. '$ _POST [ 'DBSite']'. – hakre

+0

zip에 대한'shell_exec'가 작동하지 않으면 (반환 값을 엄격하게 검사하여 함수의 매뉴얼 페이지와 비교하십시오), 인수가 너무 많은 문제가 발생할 수 있습니다. 인수에 파일 목록을 전달하는 대신'- @'를 사용하고 한 줄에 하나씩 STDIN을 통해 파일을 전달할 수 있습니다. – hakre

답변

3

명령 줄 인수에 허용되는 최대 문자 수를 초과 할 가능성이 큽니다. 원하는 작업을 위해 PHP의 built-in ZIP-support을 사용하고자 할 수 있습니다.

사이드 노트 : 사용자 입력을 받아들이는 스크립트는 아마도 이스케이프하고 싶을 것입니다. 할당 $DBSite = $_POST['DBSite']mysql_real_escape_string()을 사용해야합니다.


편집 :

우편 바이너리 Open a pipe[email protected] 옵션을 전달합니다ZipArchive부터 당신이 고려할 수있는 또 다른 옵션이, 사용할 수 없습니다. 그러면 STDIN의 파일 이름을 읽습니다. 그런 다음이 파이프에 포함될 파일 이름을 쓸 수 있습니다.

$p = popen('/usr/bin/zip [email protected] -R SearchResults.zip', 'w'); 

foreach ($files as $filename) 
    fwrite($p, $filename . "\n"); 
pclose($p); // Important. Handle needs to be closed with pclose() 
+0

새로운 ZipArchive() 라이브러리/클래스는 프로덕션 환경에서 사용할 수 없으므로 대신 Unix 유틸리티 ZIP을 사용하기로했습니다. – Chris

+0

'popen'을 사용하여 트릭을 만들었습니다. 고맙습니다. 수락하고 투표했습니다. – Chris

1

아마도 명령 줄 크기 제한 (정확히 무엇인지는 모르지만 몇 천 자 여야합니다.)을 치는 것 같습니다.

여러 작업으로 작업을 분할하십시오. 먼저 수십 개의 파일로 zip 파일을 만든 다음 더 많은 명령을 실행하여 기존 zip 파일에 추가하십시오.

관련 문제