2012-06-12 5 views
6

Tôi đang cố tải tệp từ xa và buộc tải xuống tệp đó cho người dùng cùng một lúc. Tôi không thể dán mã, mã quá dài. nhưng các chức năng curl hoạt động, nhưng vấn đề là nó không ra đặt bất cứ điều gì cho đến khi nó được tập tin từ xa đầu tiên sau đó nó buộc tải nó cho người dùng.curl tải tệp từ xa và tải xuống cùng lúc

Tôi sử dụng này để nói với curl để trả về một callback

curl_setopt($ch, CURLOPT_READFUNCTION, 'readCallback'); 

bây giờ trong chức năng readCallback của tôi, tôi làm điều này:

function readCallback($curl, $stream, $maxRead){ 
    $read = fgets($stream, $maxRead); 
    echo $read; 
    return $read; 
} 

nhưng nó không trả lại bất cứ điều gì nó chỉ chờ đợi cho đến khi lấy từ xa tệp đã hoàn tất.

+0

Tại sao bạn lặp lại * và *? – ThiefMaster

+0

echo là xuất ra các phần đã tải xuống cho người dùng và trả về là cho curl vì nó yêu cầu giá trị trả lại từ cuộc gọi lại – Danny

+0

có thể trùng lặp của [Thoát khỏi tìm nạp cURL] (http://stackoverflow.com/questions/9491621/ exit-out-of-a-curl-fetch) --- Bạn đang tìm kiếm lời gọi write, xem ở đây cho một ví dụ làm việc (và cách bạn có thể gỡ lỗi): [curl 'CURLOPT_WRITEFUNCTION' ví dụ PHP] (http: //stackoverflow.com/a/9491855/367456) – hakre

Trả lời

6

Hãy thử điều này, nó sẽ sử dụng curl để lấy tổng kích thước của tệp, sau đó tải xuống một phần của tệp proxy cho người dùng để không có chờ để cuộn tròn trước. một avi, mp4, mp3 và một exe, hy vọng nó sẽ giúp:

<?php 
$file = 'http://example.com/somefile.mp3'; 
download($file,2000); 

/* 
Set Headers 
Get total size of file 
Then loop through the total size incrementing a chunck size 
*/ 
function download($file,$chunks){ 
    set_time_limit(0); 
    header('Content-Description: File Transfer'); 
    header('Content-Type: application/octet-stream'); 
    header('Content-disposition: attachment; filename='.basename($file)); 
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
    header('Expires: 0'); 
    header('Pragma: public'); 
    $size = get_size($file); 
    header('Content-Length: '.$size); 

    $i = 0; 
    while($i<=$size){ 
     //Output the chunk 
     get_chunk($file,(($i==0)?$i:$i+1),((($i+$chunks)>$size)?$size:$i+$chunks)); 
     $i = ($i+$chunks); 
    } 

} 

//Callback function for CURLOPT_WRITEFUNCTION, This is what prints the chunk 
function chunk($ch, $str) { 
    print($str); 
    return strlen($str); 
} 

//Function to get a range of bytes from the remote file 
function get_chunk($file,$start,$end){ 
    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_URL, $file); 
    curl_setopt($ch, CURLOPT_RANGE, $start.'-'.$end); 
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'chunk'); 
    $result = curl_exec($ch); 
    curl_close($ch); 
} 

//Get total size of file 
function get_size($url){ 
    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_URL, $url); 
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
    curl_setopt($ch, CURLOPT_HEADER, true); 
    curl_setopt($ch, CURLOPT_NOBODY, true); 
    curl_exec($ch); 
    $size = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD); 
    return intval($size); 
} 
?> 
+0

Để có hiệu suất tốt hơn, hãy xem xét sử dụng ngữ cảnh luồng 'readfile' và PHP trong tương lai. Bạn sẽ thích nó. – hakre

+0

Đã nói chuyện từ xa tập tin, id tình yêu để xem một ví dụ về những gì bạn có nghĩa là ive đã cố gắng để có được đầu của tôi xung quanh câu hỏi này trong một giờ. :) –

+0

'readfile' hoạt động với các luồng PHP, ví dụ: bạn có thể làm cho nó lấy các tập tin từ xa. luồng sao chép luồng có thể là một cái gì đó đáng để xem xét nếu có thể phát trực tiếp tới đầu ra PHP trực tiếp (điều mà tôi nghĩ là có thể). Tuy nhiên tôi nghĩ rằng readfile là một chút nhẹ hơn vẫn còn. http://php.net/manual/en/book.stream.php; http://www.php.net/manual/en/stream.contexts.php và cuối cùng: http://ua2.php.net/manual/en/function.readfile.php – hakre

2

Hãy thử sử dụng curl như thế này:

$ch = curl_init($url); 
curl_setopt($ch, CURLOPT_HEADER, 1); 
curl_setopt($ch, CURLOPT_HTTPGET, 1); 
curl_setopt($ch, CURLOPT_TIMEOUT, 60); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 
$result = curl_exec($ch); 

$msg = new HttpMessage($result); 
return $msg->getBody(); 

Giá trị trả về sau đó là nội dung của tập tin được yêu cầu, mà sau đó bạn có thể xuất. Vì vậy, không cần phải gọi lại. HTTPMessage docs.

+2

nhưng không phải chờ đợi cho đến khi các tập tin kết thúc việc tải xuống bằng cách curl sau đó kết quả đầu ra nó? – Danny

+0

Có, nhưng điều đó có tiêu cực không? Việc chuyển giao phải cực kỳ nhanh vì đây là từ máy chủ này sang máy chủ khác và có thể nhanh hơn rất nhiều so với kết nối máy khách của bạn. Và bạn có thể lưu trữ các tệp đó cục bộ để người dùng tiếp theo yêu cầu cùng một tệp sẽ nhận được phản hồi nhanh hơn. Bạn đã đo sự khác biệt về thời gian tải xuống của hai phương pháp chưa? – Michael

+0

Tôi cũng muốn lưu chúng khi tôi trình bày nó cho người dùng, khi tôi tải nó xuống máy chủ, tôi cho phép người dùng tải xuống ở phía bên kia và khi tôi tải xuống, tôi có thể tự nhớ cache và tốc độ người dùng không thể so với các máy chủ ngay cả khi tôi có thể giới hạn nó. – Danny