首页 > 解决方案 > 如何使用 Laravel 在后台处理图像?

问题描述

我正在尝试上传几个 pdf 文件,使用服务将它们转换为 png 并将 png 咬数组存储到数据库。问题是当文件数量增加时,处理时间也会增加。

有什么方法可以让我执行相同的任务(上传 10 个文件),并且在第一个文件完成后,应用程序可以执行重定向并在后台处理其他 9 个文件?

谢谢!

 public function store(Request $request)
    {

        if ($_SERVER['REQUEST_METHOD'] == 'POST'){
            foreach ($_FILES['files']['name'] as $i => $name) {
                if (strlen($_FILES['files']['name'][$i]) > 1) {
                    // if (file_get_contents($_FILES['files']['tmp_name'][$i])) {
                        if ($_FILES['files']['type'][$i] == "application/pdf") {

                            // call service to cast pdf to png and return $result
                                                
                            if($result){
                                
                                $document = new Document;
                                $document->client_id = 1;
                                $document->file_name = $name;
                                $document->file_content = $result;
                                $document->save();
                            }
                        } 
                    
                }
            }
        }


        return redirect()->route('test', [Document::first()] );

标签: phplaravel

解决方案


有一种使用Laravel Jobs在后台进行所有上传的简单方法。最简单的例子是创建一个处理所有控制器逻辑的作业:

php artisan make:job ProceessFiles

现在,要让这项工作在后台工作,你必须使用 ShouldQueue 特征使其可排队:

生成的类将实现 Illuminate\Contracts\Queue\ShouldQueue 接口,向 Laravel 指示应将作业推送到队列中以异步运行。

您新创建的工作将如下所示:

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class ProceessFiles implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $files;

    /**
     * Create a new job instance.
     *
     * @param  App\Models\Podcast  $podcast
     * @return void
     */
    public function __construct($files)
    {
        $this->files= $files;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        // Process uploaded files...
        if($this->files){
          // Do a foreach loop here and do whatever logic you need. The $this->files will be passed from the controller, so you will have access to all the data here
        }
    }
}

现在,更改您的控制器代码以调用此作业:

公共功能存储(请求 $request){

    if ($_SERVER['REQUEST_METHOD'] == 'POST' && $_FILES['files']){
        //Here you can pass the files data
        dispatch(new ProceessFiles ($_FILES['files']));
    }
    return redirect()->route('test', [Document::first()] );
}

现在整个过程将在后台运行。您所要做的就是开始排队。您可以在终端中手动执行此操作:

php artisan queue:work

现在,您的队列正在等待执行 ProcessFiles 作业,当您从控制器调用它时,它将自动运行。为了更好地理解这个过程,你在我的回答开头有一个官方文档链接。如果您有任何问题,请告诉我。PS:此解决方案未经测试,因此您可能会遇到一些错误。


推荐阅读