【问题标题】:Continue PHP Operation After User Exits Early用户提前退出后继续PHP操作
【发布时间】:2017-04-01 23:47:36
【问题描述】:

我正在使用 Laravel、PHP7、PHP-FPM、APCu 和 NGINX。

我有一个 HTML 表单,用户可以在其中上传文件,它连接到 Upload.php。

文件处理:

  1. 验证
  2. 姓名
  3. 从 /tmp 移动到 /media
  4. 创建缩略图
  5. 创建数据库记录

一旦 PHP 脚本达到某个点,即使用户提前退出上传页面,我如何让它继续运行?否则一个恶意文件将留在目录中而没有数据库条目。

// Move uploaded file from /tmp to /media
Input::file('file')->move("/var/www/mysite/media", $image);

// Continue even if user exits early
// prevent a file in /media from not having a database record

// Thumbnail creation and other operations here
// May take several seconds

// Save database record
$image = new Gallery();
$image->name = $name;
$image->created_at = $date;
$image->save();

我应该使用ignore_user_abort(true) 并将操作包装在while(true) 中吗?

脚本中有其他布尔值,例如$upload = truewhile(true) 怎么知道代表 ignore_user_about(true) 而不是我设置的另一个 bool?

【问题讨论】:

  • 您可以考虑将任务传递给队列。 Laravel 有关于如何处理图像的文档(base64 编码它们)。这是一种可能性。

标签: php laravel laravel-5


【解决方案1】:

用户中止在 PHP 中不是一件容易的事情...通常,您的脚本将一直运行,直到它实际检测到客户端通过尝试将某些内容发送回浏览器而退出...在您的情况下,因为您在处理时没有发回任何东西,你应该运行完成......即使用户关闭连接......为了确保,你可以使用 register_shutdown_function() 它将在 PHP 关闭时调用......现在是小心,因为 Laravel 也有钩子......所以任何超时都会首先触发 Laravel 错误,你的第二个......但是,您可以在该函数中知道它是否正确关闭或中止......

为了玩这个功能,我创建了一条这样的路线:

 use Illuminate\Support\Facades\Log;

 Route::get('/abort', function(){
    Log::info('Entering abort route...');
    set_time_limit(5);
    register_shutdown_function(function(){
        Log::info('Entering shutdown function... status: ' . connection_status());
        switch(connection_status()){
            case CONNECTION_ABORTED:
                Log::info('Connection Aborted');
                break;
            case CONNECTION_TIMEOUT:
                echo 'Connection Timeout';
                break;
            default:
                echo 'All ok, user did not abort and function did not time out.';
        }
    });

    while(1){
        echo 'Ping<br />';
    };
});

在这里你可以捕获(我使用 Laravel 记录器进行中止...在 storage/logs/laravel.log 中找到日志)...

现在有趣的是,如果你中止这个,你将在关闭函数中得到一个中止调用,因为 while(1) 向浏览器回显“Ping”,在超时之前检测到连接丢失......但是,如果您在 while 中删除 echo 并用非缓冲工作 $cnt++ 替换它;什么的,那么即使你中止,你也只会得到超时......脚本没有检测到连接关闭......

请注意,您的处理程序在所有其他处理程序之后运行...

此外,每次脚本关闭时它都会运行...所以即使一切都很好...如默认设置:在上面切换...自然,此脚本不会因为 while(1 )...如果您想查看正常的完成行为,只需将其删除...

我认为这可能是最简单的清理方法...抓住它并进行任何您需要的清理...

希望这会有所帮助...

【讨论】:

  • 这可能需要我一段时间来测试集成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-26
  • 2018-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-25
  • 1970-01-01
相关资源
最近更新 更多