2012-12-03 15 views
14

यहाँ मेरी कोड है:file_get_contents को कैसे गति दें?

$language = $_GET['soundtype']; 
$word = $_GET['sound']; 
$word = urlencode($word); 
if ($language == 'english') { 
    $url = "<the first url>"; 
} else if ($language == 'chinese') { 
    $url = "<the second url>"; 
} 
$opts = array(
    'http'=>array(
    'method'=>"GET", 
    'header'=>"User-Agent: <my user agent>" 
) 
); 
$context = stream_context_create($opts); 
$page = file_get_contents($url, false, $context); 
header('Content-Type: audio/mpeg'); 
echo $page; 

लेकिन मैं पाया है कि इस बहुत धीमी गति से चलाता है।

क्या अनुकूलन के कोई संभावित तरीके हैं?

नोट:$url एक दूरस्थ यूआरएल है।

+2

$ url स्थानीय पथ या http: // url है? – Intrepidd

+0

@Intrepidd हां, इसके बारे में खेद है, एक दूरस्थ यूआरएल। – think123

+1

फ़ाइल का आकार क्या है और इसे लाने में कितने सेकंड लगते हैं? एक दूसरे से विभाजित करें और आपको बैंडविड्थ मिलेगा। यदि यह अप्रत्याशित रूप से धीमा है, तो आप या दूरस्थ पक्ष को और भी चाहिए! –

उत्तर

8

यह धीमा है क्योंकि file_get_contents() पूरी फ़ाइल को $page में पढ़ता है, PHP सामग्री को आउटपुट करने से पहले प्राप्त होने वाली फ़ाइल के लिए प्रतीक्षा करता है। तो आप क्या कर रहे हैं: सर्वर फ़ाइल पर पूरी फ़ाइल डाउनलोड करना, फिर इसे एक विशाल स्ट्रिंग के रूप में आउटपुट करना।

file_get_contents() रिमोट फ़ाइल के स्ट्रीमिंग या हथियार को पकड़ने का समर्थन नहीं करता है। एक विकल्प है fsockopen() के साथ कच्चे सॉकेट बनाना, HTTP अनुरोध करें, और एक लूप में प्रतिक्रिया पढ़ें, जैसा कि आप प्रत्येक खंड को पढ़ते हैं, इसे ब्राउज़र पर आउटपुट करते हैं। यह तेज़ होगा क्योंकि फ़ाइल स्ट्रीम हो जाएगी। मैनुअल से

उदाहरण:

$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30); 
if (!$fp) { 
    echo "$errstr ($errno)<br />\n"; 
} else { 

    header('Content-Type: audio/mpeg'); 

    $out = "GET/HTTP/1.1\r\n"; 
    $out .= "Host: www.example.com\r\n"; 
    $out .= "Connection: Close\r\n\r\n"; 
    fwrite($fp, $out); 
    while (!feof($fp)) { 
     echo fgets($fp, 128); 
    } 
    fclose($fp); 
} 

वहाँ अभी भी सामग्री उपलब्ध है, जबकि, प्रत्येक यात्रा यह 128 बाइट्स पढ़ता है पर ऊपर पाशन जाता है और फिर ब्राउज़र के लिए यह आउटपुट। वही सिद्धांत जो आप कर रहे हैं उसके लिए काम करेगा। आपको यह सुनिश्चित करने की आवश्यकता होगी कि आप प्रतिक्रिया HTTP हेडर को आउटपुट नहीं करते हैं जो पहली कुछ पंक्तियां होंगी, क्योंकि चूंकि आप कच्चे अनुरोध कर रहे हैं, इसलिए आपको हेडर के साथ कच्ची प्रतिक्रिया मिल जाएगी। यदि आप प्रतिक्रिया शीर्षलेख आउटपुट करते हैं तो आप भ्रष्ट फ़ाइल के साथ समाप्त हो जाएंगे।

+1

क्या आप एक उदाहरण प्रदान कर सकते हैं? 'fsockopen()' मेरे लिए ग्रीक है। – think123

+0

@ think123 ने एक उदाहरण जोड़ा – MrCode

+0

ग्रेट स्पष्टीकरण! – jan267

2

जैसा कि @MrCode द्वारा समझाया गया है, पहले फ़ाइल को अपने सर्वर पर डाउनलोड कर रहा है, फिर इसे क्लाइंट पर पास करने के लिए निश्चित रूप से दोगुना डाउनलोड समय लगेगा। यदि आप सीधे क्लाइंट को फ़ाइल पास करना चाहते हैं, तो readfile का उपयोग करें।

वैकल्पिक रूप से, के बारे में यदि आप नहीं बस ग्राहक फ़ाइल यूआरएल एक header("Location: $url") तो ग्राहक का उपयोग कर स्रोत से सीधे फ़ाइल प्राप्त कर सकते हैं रीडायरेक्ट कर सकते हैं लगता है।

+0

क्या आप 'readfile' का उपयोग करते समय अनुरोध के उपयोगकर्ता एजेंट को बदल सकते हैं? – think123

+0

यह '' संदर्भ 'संसाधन का भी समर्थन करता है, इसलिए हां। – deceze

2

इसके बजाय यह outputting से पहले पूरी फ़ाइल डाउनलोड की है, इस तरह यह पता स्ट्रीमिंग पर विचार करें:

$in = fopen($url, 'rb', false, $context); 
$out = fopen('php://output', 'wb'); 

header('Content-Type: video/mpeg'); 
stream_copy_to_stream($in, $out); 

आप साहसी रहे हैं, तो आप भी कोशिश कर सकते (लेकिन यह निश्चित रूप से प्रयोगात्मक है):

header('Content-Type: video/mpeg'); 
copy($url, 'php://output'); 

एक और विकल्प आंतरिक रीडायरेक्ट का उपयोग कर रहा है और आपके वेब सर्वर प्रॉक्सी को आपके लिए अनुरोध कर रहा है। यह PHP को कुछ और करने के लिए मुक्त कर देगा। my post regarding X-Sendfile and friends भी देखें।

संबंधित मुद्दे