2012-04-30 1 views
0

파일을 압축하여 사용자가 다운로드 할 수 있도록 허용하는 웹 사이트의 PHP 페이지에서 작업하고 있습니다. zip의 파일 크기는 몇 MB에서 100MB까지 다양합니다. 내 PHP 스크립트는 임시 디렉토리에 zip 파일을 만든 다음 파일 내용을 브라우저에 씁니다. 이 작업이 끝나면 스크립트는 MySQL 데이터베이스의 다운로드 카운터를 업데이트하고 임시 디렉토리에서 zip 파일을 삭제합니다.대용량 파일 다운로드 후 PHP 스크립트가 완료되지 않는다

30 초 이상 걸리는 대용량 zip 다운로드가 나올 때까지이 모든 것이 정상적으로 작동합니다. php.ini 파일의 max_execution_time이 30으로 설정되었으므로, set_time_limit(0)을 사용하거나 max_execution_time을 사용하면 동일한 결과가 발생합니다. zip 파일은 브라우저에서 성공적으로 모든 올바른 파일을 다운로드하지만 데이터베이스가 업데이트되지 않고 서버의 임시 zip 파일이 삭제되지 않기 때문에 나중에 스크립트가 중지 된 것으로 보입니다.

아파치와 PHP 5.2가 설치된 Linux 환경입니다.

이 웹 사이트는 GoDaddy에서 호스팅되므로 스크립트가 실행할 수있는 시간 제한을 변경하는 데 제한이 있는지는 잘 모르겠지만 기본적으로이 특정 스크립트를 완료 할 때까지 무기한 실행하도록하고 싶습니다.

왜 시간 제한이나 임시 해결책을 설정할 수 없는지에 대한 의견이 있으십니까?

여기 내 코드입니다 :

<?php 

// Don't stop the script if the user 
// closes the browser 
ignore_user_abort(true); 
set_time_limit(0); 

// Generate random name for ZIP file 
$zip_file = ""; 
$characters = "abcdefghijklmnopqrstuvwxyz"; 

do 
{ 
    $zip_file = "tmp/"; 

    for ($p = 0; $p < 10; $p++) 
     $zip_file .= $characters[mt_rand(0, strlen($characters))]; 

    $zip_file .= ".zip"; 
} while (file_exists($zip_file)); 

// Prepare ZIP file 
$zip = new ZipArchive(); 

/* Open and add files to ZIP (this part works fine) 
. 
. 
. 
*/ 

// Close and save ZIP 
$zip->close(); 

// Check browser connection 
if (connection_status() == 0) 
{ 
    // Send ZIP 
    header("Content-Type: application/zip"); 
    header("Content-Length: " . filesize($zip_file)); 
    header("Content-Disposition: attachment; filename=Download.zip"); 
    header("Cache-Control: no-store, no-cache, must-revalidate"); 
    header("Cache-Control: post-check=0, pre-check=0", false); 
    header("Pragma: no-cache"); 
    header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); 
    header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); 

    // Save and then delete file 
    //readfile($zip_file); 
    if ($file = fopen($zip_file, "r")) 
    { 
     // Set buffer size 
     $buffer_size = 1024 * 8; 

     // While we're still transmitting 
     // send over bytes! 
     while(!feof($file) && (connection_status() == 0)) 
     { 
      print(fread($file, $buffer_size)); 
      flush(); 
      usleep(10000); //<!-- Download speed cap 
     } 

     // Close file descriptor 
     fclose($file); 
    } 
} 

/* Update database download counter if connection_status() == 0 
. 
. 
. 
*/ 

// Delete the file 
unlink($zip_file); 

?> 

UPDATE : 난 그냥 내 로컬 웹 서버에서 다른 서버로 다운로드하고 시도하고 다운로드 시간을 느리게 만에 usleep 명령을 승진. 총 다운로드 시간이 1 분 조금 넘었고 데이터베이스가 업데이트되어/tmp에서 파일이 삭제되었습니다. 내 로컬 환경은 Windows 7 상자에서 Apache 및 PHP 5.3을 사용하여 EasyPHP를 실행합니다. 이게 바로 GoDaddy와 관련이있는 것 같습니다. 또한

는 모두 GoDaddy와 지역 사이트에, 난 내 스크립트에서 호출되기 전에 및 set_time_limitmax_execution_time를 인쇄 결과는 그래서 사물의에서 GoDaddy 측에서 무슨 일이 일어나고 있는지 확실하지 않다 각각 30과 0이었다.

+0

디스크에 임시 파일을 생성하지 않는 이유는 무엇입니까? –

+0

왜 아파치가 큰 다운로드를 처리하게하지 않습니까? PHP 스크립트는 시간이 초과 될 수있는 링크에 300 스타일을 응답 할 수 있습니다. –

+0

PHP가 안전 모드로 실행되고 있습니까? GoDaddy 호스팅에 대한 확신이 없습니다. –

답변

0

아직도 내가 위에 사용하고있는 코드가 호스팅 사이트에서 작동하지 않는 이유는 확실하지만 해결 방법을 찾았습니다. 라이브 사이트에서 register_shutdown_function 호출을 PHP로 사용하면 데이터베이스가 올바르게 업데이트되고 파일이 삭제됩니다.

<?php 

$filesize = 0; 
$total_bytes_read = 0; 
$download_query = ""; 
$zip_file = "tmp/download.zip"; 

register_shutdown_function("shutdown"); 

/* Other code for creating ZIP file and reading it out to the browser 
. 
. 
. 
*/ 

function shutdown() 
{ 
    global $filesize; 
    global $total_bytes_read; 
    global $zip_file; 
    global $download_query; 

    // Update the database if file was fully downloaded 
    if ($filesize != 0 && $filesize == $total_bytes_read) 
    { 
     /* Do database update with $download_query 
     . 
     . 
     . 
     */ 
    } 

    // Delete the file 
    unlink($zip_file); 
} 

?> 
0
  1. HTTP 서버 구성에 문제가 있습니까? 무엇을 사용하고 있으며 구성은 무엇입니까?
  2. 다른 변형으로, 다운로드가 끝나면 연결 상태가 0이 아니어도됩니다. 따라서 데이터베이스 업데이트 조건의 코드가 전혀 평가되지 않습니다.
  3. php.ini에서 오류 로깅이 설정되어 있습니까? 그렇다면 php.error.log를 살펴 보았습니다. 아마도 메모리 누수와 "메모리 부족"오류가있을 수 있습니다.
+0

Apache를 실행하는 Linux 환경의 GoDaddy 계정입니다. 오류 로깅을 켜서 로그가 생성되었는지 확인합니다. – Zac

+0

php.ini의 error_log를 유효한 파일 이름으로 설정했지만 파일이 생성되지 않습니다. GoDaddy에는 오류 로깅 기능이 있지만 경제적 인 Linux 계정에는 사용할 수 없습니다. 불행히도. – Zac

0

당신은 당신의 php5.ini에서 max_execution_time을 설정하고 PHP 정보 페이지로이를 확인 할 수 있어야한다 :

다음은 셧다운 기능 코드입니다. PHPinfo 페이지에서 php5.ini의 섹션과 출력물을 제공 할 수 있습니까?

+0

php5.ini에서 max_execution_time을 3600으로 변경하고 phpinfo()를 실행하고 출력에 3600을 표시했으나 스크립트가 30 초 이상 걸린 경우 데이터베이스와 서버 파일이 삭제되지 않습니다. 다운로드가 브라우저에서 완료 되더라도 . register_function_shutdown을 사용하는 것이 더 나은 방법입니다. – Zac

관련 문제