How to speed up file_get_contents?

前端 未结 3 1237
暗喜
暗喜 2021-02-07 19:44

Here\'s my code:

$language = $_GET[\'soundtype\'];
$word = $_GET[\'sound\'];
$word = urlencode($word);
if ($language == \'english\') {
    $url = \"

        
相关标签:
3条回答
  • 2021-02-07 19:56

    Instead of downloading the whole file before outputting it, consider streaming it out like this:

    $in = fopen($url, 'rb', false, $context);
    $out = fopen('php://output', 'wb');
    
    header('Content-Type: video/mpeg');
    stream_copy_to_stream($in, $out);
    

    If you're daring, you could even try (but that's definitely experimental):

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

    Another option is using internal redirects and making your web server proxy the request for you. That would free up PHP to do something else. See also my post regarding X-Sendfile and friends.

    0 讨论(0)
  • 2021-02-07 20:06

    It's slow because file_get_contents() reads the entire file into $page, PHP waits for the file to be received before outputting the content. So what you're doing is: downloading the entire file on the server side, then outputting it as a single huge string.

    file_get_contents() does not support streaming or grabbing offsets of the remote file. An option is to create a raw socket with fsockopen(), do the HTTP request, and read the response in a loop, as you read each chunk, output it to the browser. This will be faster because the file will be streamed.

    Example from the Manual:

    $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);
    }
    

    The above is looping while there is still content available, on each iteration it reads 128 bytes and then outputs it to the browser. The same principle will work for what you're doing. You'll need to make sure that you don't output the response HTTP headers which will be the first few lines, because since you are doing a raw request, you will get the raw response with headers included. If you output the response headers you will end up with a corrupt file.

    0 讨论(0)
  • 2021-02-07 20:16

    As explained by @MrCode, first downloading the file to your server, then passing it on to the client will of course incur a doubled download time. If you want to pass the file on to the client directly, use readfile.

    Alternatively, think about if you can't simply redirect the client to the file URL using a header("Location: $url") so the client can get the file directly from the source.

    0 讨论(0)
提交回复
热议问题