文件保护服务器的麻烦 - readfile();

时间:2011-02-09 08:39:52

标签: php file download

我将以下脚本编写为避免将受保护文件暴露给在我的Web应用程序中登录的用户。

这适用于小文件...但在某些平台上,例如iPad,Android,Internet Explorer以及有时Safari我有时会有时(约50%)文件服务...就像在trasfer中间的连接停止一样。

我在Ubuntu Server 10.04上运行Apache2.2 / PHP 5.3。

有谁能建议如何改进它? 感谢。

<?php

// my bootstrap with env vars
// some includes ..

if(! @constant('APP_BASE_PATH') )   { header('HTTP/1.1 502 Bad Gateway'); die(''); }

// allowed types
$allowed_types = array( 'application/pdf', 'image/png', 'image/jpeg' );


// my custom function to check login
if( isUserLogged($_SESSION) )
{
    // if file exist
    if(! is_file( $file ) )
        { header('HTTP/1.1 400 Bad Request'); die('unable to find target file'); }

    // if is permitted
    $type = exec('file -bi ' . escapeshellarg($file) );
    if(! in_array( $type, $allowed_types ) )
        { header('HTTP/1.1 400 Bad Request'); die(''); }

    // lenght calc
    $content_lenght = intval( sprintf( "%u", filesize( $file ) ) );

    // last modify
    $last_modified = gmdate('D, d M Y H:i:s', filemtime( $file ) ) . ' GMT';

    // generating l'etags
    $stat = stat($file);
    $etag = sprintf( '"%x-%x-%s"' , $stat['ino'] , $stat['size'] , base_convert( str_pad( $stat['mtime'], 16, '0' ) , 10 , 16 ) );

    // disable gzip compression
    @apache_setenv ( 'no-gzip', 1 );
    @ini_set ( 'zlib.output_compression', 0 );
    ini_set( 'display_error', 0);

    header ( 'HTTP/1.1 200 OK' );
    header ( 'Content-Type: ' . $type );
    header ( 'Content-Length: ' . $content_lenght );
    header ( 'Etag: ' . $etag );
    header ( 'Last-Modified: ' . $last_modified );

    // if that's a PDF, try to force
    if( strpos($type, 'application/pdf') !== FALSE ) {
        header ( 'Content-Description: File Transfer' );
        header ( 'Content-disposition: attachment; filename=' . basename ( $file ) );
        header ( 'Content-Transfer-Encoding: binary');
    }
    // serve file
    readfile ( $file );

} else {
    header('HTTP/1.1 401 Unauthorized');
}

1 个答案:

答案 0 :(得分:0)

这条线存在问题:

$type = exec('file -bi ' . escapeshellarg($file) );

在Ubuntu 9.10服务器上,shell命令的返回值为:

image/jpeg; charset=binary

所以你的支票总是会失败。您需要将命令更改为:

$type = exec('file --mime-type -b ' . escapeshellarg($file) );

哪个应该给你:

image/jpeg

此外,最好通过curl而不是浏览器来测试您的API调用。