2

我正在编写一个代理脚本来访问 WWW 公共目录之外的文件。一切都按预期工作,它成功返回了音频、图像、文本和 Flash MIME 类型的文件。但是,我无法使用任何视频 MIME 类型。我能得到的最好结果是 Firefox 中出现一条错误消息,指出“无法播放视频,因为文件已损坏。”

require_once(dirname(dirname(dirname(__FILE__))).'/config.php');

require_login(); // Users must be logged in to access files

global $CFG;

if(isset($_GET['content']))
{
    // Clean up content path
    $swf_disallowed = array('../','//','///');
    $swf_replace = array('','/','/');
    $swf_content = str_replace($swf_disallowed,$swf_replace,$_GET['content']);
} else {
    die;
}

// Make sure all the condtions are met before attempting to server file:
// must have a "." within 4 chacters of the end
if(strrpos($swf_content,'.') > strlen($swf_content) - 6)
{
    $swf_file_extention = substr($swf_content,strrpos($swf_content,'.')); // Get file extension to set MIME type
    $swf_file = $CFG->dataroot.$CFG->swf_content_dir.$swf_content; // Full path to file
} else {
    die;
}

// Please note: extension=php_fileinfo.dll or extension=php_fileinfo.so
// must be enabled for the following class and function to be called.
//$swf_finfo = new finfo(FILEINFO_MIME);
//echo $swf_finfo->file($swf_file);

// Serve file
if (file_exists($swf_file) && is_readable($swf_file))
{
    // set the MIME type  TODO - Test these in Firefox, IE, Chrome, Safari, Opera and JW Player
    switch ($swf_file_extention)
    {

    // AUDIO
    case '.aac':
    $swf_mime = 'audio/mp4'; // works in Firefox
    break;

    case '.f4a':
    $swf_mime = 'video/mp4'; // not tested
    break;

    case '.m4a':
    $swf_mime = 'video/mp4'; // not tested
    break;

    case '.mp3':
    $swf_mime = 'audio/mpeg'; // works in Firefox
    break;

    //IMAGE
    case '.gif':
    $swf_mime = 'image/gif'; // works in Firefox
    break;

    case '.jpeg':
    $swf_mime = 'image/jpeg'; // works in Firefox
    break;

    case '.jpg':
    $swf_mime = 'image/jpeg'; // works in Firefox
    break;

    case '.png':
    $swf_mime = 'image/png'; // works in Firefox
    break;

    // TEXT
    case '.smil':
    $swf_mime = 'text/xml'; // works in Firefox
    break;

    case '.xml':
    $swf_mime = 'text/xml'; // works in Firefox
    break;

    // VIDEO
    case '.f4v':
    $swf_mime = 'video/x-flv'; // offers file.php download
    break;

    case '.flv':
    $swf_mime = 'video/x-flv'; // offers file.php download
    break;

    case '.m4v':
    $swf_mime = 'video/x-m4v'; // offers file.php download
    break;

    case '.mov':
    $swf_mime = 'video/mp4'; // offers file.php download
    break;

    case '.mp4':
    $swf_mime = 'video/mp4'; // doesn't work in Firefox
    break;

    // FLASH
    case '.swf':
    $swf_mime = 'application/x-shockwave-flash'; // works in Firefox
    break;

    default: 
    $swf_mime = false;
    }

// if a valid MIME type exists, display the image
// by sending appropriate headers and streaming the file
if ($swf_mime)
{
    header('Content-type: '.$swf_mime); 
    header('Content-length: '.filesize($swf_file)); 
    $file = @ fopen($swf_file, 'rb');
    if ($file)
    {
        fpassthru($file);
        exit;
    }
}
}
// no closing PHP tag here!
4

1 回答 1

1

好的,找到了我自己的问题的解决方案。对于大文件,似乎需要在 fpassthru() 之前立即调用 ob_end_clean()。

// if a valid MIME type exists, display the image by sending appropriate headers and streaming the file
if ($swf_mime)
{
    header('Content-type: '.$swf_mime); 
    header('Content-length: '.filesize($swf_file)); 
    $file = @ fopen($swf_file, 'rb');
    if ($file)
    {
        // Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 264744961 bytes)
        // fpassthru handles video files badly! readfile is the same!
        ob_end_clean();//required here or large files will not work
        fpassthru($file); 
        exit;
    }
}
于 2013-06-21T23:39:42.370 回答