【问题标题】:PHP File Upload, using the FILES superglobal arrayPHP 文件上传,使用 FILES 超全局数组
【发布时间】:2011-02-16 15:45:16
【问题描述】:

假设我正在为一个项目设置上传功能。 我正在使用 PHP5,我想知道是否通过使用 $_FILES 超全局数组,我可以访问“tmp_name”数组键,这是正在上传的文件的临时路径和名称,以显示图像的预览, 在将其移动到服务器中的“上传”文件夹之前。

我的想法是这样的: 使用 jQuery 检测“文件”输入文件何时更改(当用户选择图像文件时),然后进行 ajax 调用以上传文件,这将在我使用“move_uploaded_file”之前将其移动到临时文件夹。 如果我能以某种方式访问​​“tmp_name”数组键,我可能会将其放入“img”标签中以显示预览。 稍后单击提交按钮时将文件移动到其最终位置。

我不是要任何代码示例或任何东西,因为我很高兴自己完成这项工作,我只是想知道是否可以通过任何方式访问该数组键。

【问题讨论】:

    标签: php file upload


    【解决方案1】:

    是的,你可以。

    在 PHP 中,当用户提交带有超全局 $_FILES 的表单时,会填充有关已上传文件的有用信息。在里面你会发现每个上传文件的原始名称、内容类型、服务器上的临时上传位置、错误代码和大小(以字节为单位)。

    取自Fixing the $_FILES superglobal

    这是从$_FILES 数组的网站获取的示例print_r 输出,

    Array
     (
        [download_zip] => Array
         (
            [name] => dummy.txt
            [type] => text/plain
            [tmp_name] => /Applications/MAMP/tmp/php/php5TBPsw
            [error] => 0
            [size] => 1
         )
    
        [download_screenshot] => Array
         (
            [name] => dummy.txt
            [type] => text/plain
            [tmp_name] => /Applications/MAMP/tmp/php/phpTncd39
            [error] => 0
            [size] => 1
         ) 
    )
    

    您可以使用$files_array['download_zip']['tmp_name'] 语法访问tmp_name

    更新:

    $path = $files_array['download_zip']['tmp_name'];
    echo "<img src='$path'>"; 
    

    【讨论】:

    • 太好了,这正是我所说的,现在,就像我说的那样,是否可以使用“tmp_name”的值(稍微调整一下)作为“src”属性“img”标签?由于我还没有完成“move_uplooaded_file”,我可能会从它的临时位置显示图像,直到它最终移动到服务器?我对么?谢谢
    • 为了清楚起见,您想在img 标记中将tmp_name 设置为src 属性吗?但是,我不确定您是否可以随心所欲,但您可以试一试,看看它是如何工作的。
    • 是的,这就是我想要做的,显然填空以获得有效的“img”标签。谢谢。我试试看。
    • 您的临时路径是否在 Web 根目录中?
    【解决方案2】:

    要在图像标签中使用这些,您需要将相关的临时文件存储在 web 根目录中的某个位置,因为它们通常位于文件系统中的其他位置,位于 web 根目录之外,并且您不想输出用户的该路径,因为它既无用(img 标签无法映射到该路径),又不安全(您正在泄露有关文件系统的信息)。

    您可以通过 a) 将每个文件复制到 webroot 中的某个位置(成本高昂),或 b) 更改您的配置以将所有上传的文件放入web 根目录中的 temp 文件夹(很大的安全隐患)。

    在计划此过程时请牢记安全...

    请注意其他临时文件的安全性。确保只有与此应用程序的这一部分相关的内容存储在 Web 根目录中。您不希望发现您已经提供了足够的信息来允许某人计算对其他文件的访问权限并且存在某种跨用户数据泄露,因为其他上传的数据在您的网络中可用(即使是很短的时间)根。

    这可能是更好的方法:

    也许更好的解决方案是获取临时名称,以某种方式对其进行混淆,将其添加到将其传递给网守文件的路径中,然后将其发送。

    有点像

    /images/path/to/gatekeeper.png?name=[obfuscated file name here]
    

    然后您可以使用 /images/path/to/.htaccess 来确保网守被视为 php 文件而不是 png 文件,方法是添加:

    <Files gatekeeper.png>
        ForceType application/x-httpd-php
    </Files>
    

    现在,网守可以对文件名进行去混淆处理,从临时路径中提取并发送它,而无需向用户透露任何内容、移动实际文件或更改您的配置。

    请确保您不希望文件保留,因为如果它们稍后刷新,并且文件已移动(几乎肯定会移动),它将只是一个损坏的图像。也许与看门人一起检查存在,如果找不到,则给他们一个“文件不再可用”的图像。您还可以强制仅发送图像文件,或在网守级别强制发送其他安全问题。

    您可以这样做(从内存中键入,可能不会运行,并且没有处理错误,缺失值等,但您应该能够以此为起点......):

    <?php
    // This is all inside gatekeeper.png, which is just a .php file with a .png extension
    // It's not very good code, just an example to point you in the right direction.
    
    // Specify this will be a png file for the browser...
    header("content-type: image/png");
    
    
    //Read the file name from the $_GET and un-obfuscate it.
    $file = "/path/to/temp/directory/outside/file/root/that/we/hopefully/have/access/to/";
    $file .= $_GET["name"];
    
    
    // Check that the file exists, and send a "not found" image if not.
    // http://us.php.net/manual/en/function.file-exists.php
    if (!file_exists($file)) {etc...}
    
    
    // Read the image file, send it to the user, and close it...
    // http://us.php.net/manual/en/function.imagepng.php
    $im = imagecreatefrompng($file);
    imagepng($im);
    imagedestroy($im);
    
    
    die();
    
    ?>
    

    【讨论】:

    • 非常感谢 Eli,这让我对安全隐患有了深刻的了解。我真的很感激。
    猜你喜欢
    • 2014-02-22
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 2020-05-10
    • 2013-10-18
    • 1970-01-01
    • 2012-03-27
    相关资源
    最近更新 更多