2013-06-28 7 views
5

.mp4 파일을 다운로드하려고합니다. (약 1.3GB 크기). PHP 파일에서 강제로 다운로드 중입니다.

<?php 
$path = "video.mp4"; 
header('Accept-Ranges: bytes'); // For download resume 
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
header('Content-Description: File Transfer'); 
header('Content-Disposition: attachment; filename="'.basename($path).'"'); 
header('Content-Length: ' . filesize($path)); // File size 
header('Content-Transfer-Encoding: binary'); // For Gecko browsers mainly 
header('Content-Type: application/octet-stream'); 
header('Expires: 0'); 
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($path)) . ' GMT'); 
header('Pragma: no-cache'); 
ob_clean(); 
flush(); 
readfile($path); 

내가 내 PHP 파일을 열고, 파이어 폭스는 "저장하려면"메뉴 팝업 : 내가 사용하여 다음과 같은거야. 크기가 옳다. 다른 이름으로 저장을 눌러 내 바탕 화면으로 이동하십시오. 최종 다운로드 파일은 약 400MB (330, 463 및 440)의 임의 크기로 나열됩니다.

응답 헤더는 다음과 같습니다

Connection: Keep-Alive 
Content-Disposition: attachment; filename="//www.frederikspang.dk/elevgallavideo.mp4" 
Content-Length: 1422778850 
Content-Type: video/mp4 
Date: Sun, 30 Jun 2013 22:12:30 GMT 
Keep-Alive: timeout=10, max=50 
Pragma: public 
Server: Apache 
content-transfer-encoding: binary 
+1

실행 제한 시간에 맞춰 실행 중일 수 있습니다. 동일한 시간 후에 다운로드가 항상 중단됩니까? –

+0

Resumable 파일 다운로드에는 이보다 훨씬 많은 코드가 필요합니다. 그래서 Accept-Ranges를 제거해야합니다. 참조 : http://stackoverflow.com/questions/157318/resumable-downloads-when-using-php-to-send-the-file –

+0

실제로 출력 버퍼링을 사용하고 있습니까? 그렇지 않으면 readfile 명령이 클라이언트에 직접 데이터를 출력하므로 ob_clean() 및 flush()가 필요하지 않습니다. – dethtron5000

답변

0
<?php 
$filename = "theDownloadedFileIsCalledThis.mp4"; 
$myFile = "/absolute/path/to/my/file.mp4"; 

// Add bellow code for mime type 
$ext=strtolower(substr($fl,strrpos($myFile,"."))); 
$mime_types = array(
      '.txt' => 'text/plain', 
      '.htm' => 'text/html', 
      '.html' => 'text/html', 
      '.php' => 'text/html', 
      '.css' => 'text/css', 
      '.js' => 'application/javascript', 
      '.json' => 'application/json', 
      '.xml' => 'application/xml', 
      '.swf' => 'application/x-shockwave-flash', 
      '.flv' => 'video/x-flv', 

      // images 
      '.png' => 'image/png', 
      '.jpe' => 'image/jpeg', 
      '.jpeg' => 'image/jpeg', 
      '.jpg' => 'image/jpeg', 
      '.gif' => 'image/gif', 
      '.bmp' => 'image/bmp', 
      '.ico' => 'image/vnd.microsoft.icon', 
      '.tiff' => 'image/tiff', 
      '.tif' => 'image/tiff', 
      '.svg' => 'image/svg+xml', 
      '.svgz' => 'image/svg+xml', 

      // video 
      '.3gp' => 'video/3gpp', 
      '.3g2' => 'video/3g2', 
      '.avi' => 'video/avi', 
      '.mp4' => 'video/mp4', 
      '.asf' => 'video/asf', 
      '.mov' => 'video/quicktime', 
     ); 

if (array_key_exists($ext, $mime_types)){ 
    $mm_type=$mime_types[$ext]; 
}else{ 
    $mm_type="application/octet-stream"; 
} 
$mm_type="application/octet-stream"; 

header("Cache-Control: public, must-revalidate"); // Avoid this line 
header("Pragma: public"); // Add this line 
header("Pragma: hack"); // Avoid this line 
header("Content-Type: " . $mm_type); 
header("Content-Length: " .(string)(filesize($myFile))); // Avoid this line 
header('Content-Disposition: attachment; filename="'.$filename.'"'); 
header('Content-Length: ' . filesize($myFile)); // Add this line 
header("Content-Transfer-Encoding: binary\n"); 
ob_clean(); // Add this line 

readfile($myFile); 

?> 
+0

매우 명확하지 않은 대답입니다. 잘 문서화되지 않았습니다. "피하십시오", "추가하다", 그리고 왜 그렇게하는지 자세히 설명해주십시오. –

+0

MIME 형식에 대한 참조가 유용하며 헤더 선언이 의미가 있습니다 ... "피하십시오"는 분명히 "사용하지 마십시오"를 의미하고 "추가"는 "추가"를 의미합니다. 그가 무엇을 할 수 있었는지에 대한 더 나은 설명이 제공되었습니다. – zgr024

+0

'$ mm_type = "application/octet-stream"을 어쨌든 설정하려는 경우 모든 MIME 유형 쓰레기는 무엇입니까? –

1

이 어렵다 - 대부분의 PHP 설정은 30 초 후에 실패합니다. php.ini를 소유하고 계시다면 php.ini를 더 오래 사용할 수 있습니다. 그러나 여전히 - 그럴만 한 가치가 있습니까? 내 말은 - 파일이 더 커지거나 네트워크가 느려질 수 있다는 것입니다. 그리고 한 번 더 초과하면 시간 초과가 발생합니다.

큰 사이즈의 파일을 작은 덩어리로 다운로드하는 이유입니다. Half Crazed은 그 코드를 보여주었습니다. THIS 답변 - 이뿐 만 아니라 고객이 전송을 협상하는 방법 중 하나를 고려합니다. 좋은 시작).

예를 들어 Mega.co.nz는 새로운 html5 기능을 사용합니다. 청크를 사용하여 브라우저에서 파일을 다운로드하고 사용자의 파일에 가입 한 다음 브라우저 디스크 공간에서 다운로드합니다. 파일을 다시 시작하거나 파일을 일시 중지 할 수 있습니다. (죄송합니다 - 코드가 없으므로 하나의 언어 (php, js) 이상 포함).

PS :

$handle=fopen($path, 'rb'); 
while (!feof($handle)) 
{ 
    echo fread($handle, 8192); 
    flush(); 
} 
fclose($handle); 

이 전체가 메모리에 파일을 한 번에 8KiB의 단지 부분을 넣은 다음 사용자에게 전송하지 않습니다 : 당신이 readfile($path);로 변경합니다.

+0

이것이 사실이지만, Apache2의 Keep-Alive는 충분히 높지 않았습니다. (그냥이 질문을 다시 본, 내가 대답 줄 줄 알았는데) –

+0

죄송하지만 늦게 대답하지만, 다른 이유로 사용 지속 ... 대부분의 서버는 60seconds 후에 php를 죽일 것입니다 - 여전히 파일을 보내는 경우에도 살해 당할 것입니다.) 그리고 그 한계를 드러내는 것은 종종 현명하지 않습니다. – Seti

관련 문제