【问题标题】:Pass uploaded file between PHP scripts在 PHP 脚本之间传递上传的文件
【发布时间】:2012-07-09 19:50:30
【问题描述】:

我有一个页面,用户可以在其中上传 HTML 文件以用作主题。在向用户显示某些选项之前,HTML 文件对其执行了一些检查。用户填写与 HTML 文件相关的表单,并提交表单。但是,由于脚本结束后临时文件夹中的文件被销毁,我不知道一旦填写并重新提交表单后如何获取 HTML 文件,而不是让用户重新上传文件,这依赖于他们上传相同的文件,并且还会让他们上传两次,这是违反直觉的,并且可能是大文件的问题。
这是代码(减少以使其更易于阅读/理解)。表单提交给自己,因此两个“步骤”使用相同的 PHP 文件。

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    // Form has been submitted
    $files = $_FILES['file'];
    <form method="POST">
        /* Options about the uploaded HTML file are generated using PHP and displayed here */
        <input type="submit">
    </form>
} else {
    ?>
    <form method="POST" enctype="multipart/form-data">
        <label for="file">Theme File(s)</label>
        <input type="file" name="file[]" multiple="multiple">
        <input type="submit">
    </form>
    <?php
}

我尝试使用&lt;input type="file" name="file[]" multiple="multiple" value="&lt;?php echo $files; ?&gt; &gt;,但这不起作用,并且还需要用户重新上传文件,如果文件太大,这可能会出现问题。
我在想可能有一种方法可以在内部传递文件,并检查文件是否已上传或传递给脚本而不是&lt;input type="file" name="file[]" multiple="multiple"&gt;,但我找不到这样做的方法。

【问题讨论】:

    标签: php html file-upload


    【解决方案1】:

    您需要创建自己的临时文件,并在两个脚本之间传递名称。

    例如,在您的“第一个脚本”中(即文件首次上传时),您会:

    $uniqName = uniqid('upload_', TRUE);
    $tmpFile = "/tmp/$uniqName.html";
    move_uploaded_file($_FILES['file']['tmp_name'][0], $tmpFile);
    

    然后当你从这个上传的结果生成表单时,你会添加

    <input type="hidden" name="uniqName" value="<?php echo $uniqName; ?>" />
    

    ...这样当您进入“第二个脚本”时(提交调查表后),您可以通过以下方式访问该文件:

    $tmpFile = "/tmp/".basename($_REQUEST['uniqName']).".html";
    

    当然,这取决于人们未能提交第二个表单的可能性,因此您最终会在您的临时目录中乱扔“孤立文件”,因此您需要实施某种形式的检查,以便在提交后删除文件在一段时间内处于非活动状态 - 您可以根据文件的最后修改时间来确定。

    编辑

    这是一个示例,说明如何在没有 cron 作业的情况下随机运行作业以保持 /tmp 目录整洁:

    $probabilityDivisor = 10; // 1/10 chance of running
    $uploadTTLSecs = 1800; // 30 minutes
    
    if (mt_rand(1, $probabilityDivisor) / $probabilityDivisor == 1) {
      foreach (glob('/tmp/upload_*') as $file) {
        // Iterate files matching the uniqids you generate
        if (time() - filemtime($file) >= $uploadTTLSecs) {
          // If file is older than $uploadTTLSecs, delete it
          unlink($file);
        }
      }
    }
    

    这与 PHP session garbage collectors 的操作方式相似。由于操作的简单性,这不应以任何有意义的方式对用户体验产生不利影响。

    【讨论】:

    • 我想过这样的事情,但你已经对我说得很清楚了,谢谢。有没有办法在没有 cron 作业的情况下删除这些临时文件(我知道的唯一方法)?
    • 您可以在上传文件时随机运行作业(类似于Drupal poormanscron 模块)我将使用示例代码进行编辑。
    • 我将不得不再玩一些,但总的来说它看起来不错。但是,当我使用$tempFolderName = sys_get_temp_dir() . '/' . uniqid('upload_', TRUE) . '/'; 时,$tempFolderName 的值是C:\Windows\TEMP/upload_4ffc4373242041.76382376/,它有两处问题。 1) 那是 windows 临时文件夹,而不是 php 文件夹,这可能会导致问题(?) 2) 我怎么知道使用“/”或“\”?我假设这是基于操作系统的,但我希望它可以跨操作系统运行。 (注意:我想将所有文件放在 PHP 临时目录(公共视图外)的一个文件夹中,名称随机)
    • 另请注意:我对数字 1 的看法可能完全错误,这可能是预期的结果;我只是认为它会存储在 PHP tmp 文件夹中。
    • @JosephDuffy 在 Windows 上运行 PHP 时,PHP tempdir == Windows tempdir - 这不会导致问题,只要 Web 服务器用户有权写入它(它很可能会)。您可以在 Windows 上使用/,它会起作用,所以我总是在每个脚本中使用/ 以实现交叉兼容性。但是,如果您担心它,您可以使用DIRECTORY_SEPARATOR 常量来获取系统的默认字符。
    【解决方案2】:

    您可以尝试以下方法:

    1. 使用 move_uploaded_file() 并将文件从临时位置移动到服务器上的永久位置。请务必为您的移动文件指定一个唯一的名称,例如 'file-' 。时间() 。 '.jpg' 什么的。

    2. 上传后不久,注册一个Session变量并将文件名放入其中。

    3. 一切都结束后,您可以使用 unset() 删除文件

    现在该文件安全地位于您的服务器上,您也可以通过会话访问它。

    希望这会有所帮助:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-06
      • 1970-01-01
      • 2011-01-19
      • 2013-01-07
      • 1970-01-01
      • 2018-10-20
      相关资源
      最近更新 更多