如何在上传到AmazonS3时,使用beanstalkd在laravel中正确排队处理图像



我正在用laravel做一些测试,将图像加载到AmazonS3,并用beanstalkd排队处理图像。请注意,这只是测试。

这是我的实现:

//routes.php

Route::post('/', function()
{
    $validator = Validator::make(Input::all(), array(
        'title' => 'required',
        'file'  => 'required|mimes:jpeg,jpg,png',
    ));
    if( $validator->fails() )
    {
        return Redirect::to('/');
    }
    // Upload File
    $file = Input::file('file');
    $now = new DateTime;
    $hash = md5( $file->getClientOriginalName().$now->format('Y-m-d H:i:s') );
    $key = $hash.'.'.$file->getClientOriginalExtension();
    $s3 = AWS::createClient('s3');
    $s3->putObject(array(
        'Bucket'      => 'bellated',
        'Key'         => $key,
        'SourceFile'  => $file->getRealPath(),
        'ContentType' => $file->getClientMimeType(),
    ));
    // Create job
    Queue::push('ProcWorkerImageProcessor', array(
        'bucket'   => 'bellated',
        'hash'     => $hash,
        'key'      => $key,
        'ext'      => $file->getClientOriginalExtension(),
        'mimetype' => $file->getClientMimeType(),
    ));
    Log::info('queue processed');
    return Redirect::to('/complete');
});

//图像处理器

<?php namespace ProcWorker;
use ImagineGdImagine;
use ImagineImageBox;
class ImageProcessor {
    protected $width;
    protected $height;
    protected $image;
    public function fire($job, $data)
    {
           $s3 = AWS::createClient('s3');

        try {
   $response = $s3->getObject(array(
            'Bucket'      => $data['bucket'],
            'Key'         => $data['key'],
        ));
} catch (Exception $e) {
   return; 
}
        $imagine = new Imagine();
        $image = $imagine->load( (string)$response->get('Body') );
        $size = new Box(100, 100);
        $thumb = $image->thumbnail($size);
        $s3->putObject(array(
            'Bucket'      => 'bellated',
            'Key'         => $data['hash'].'_100x100.'.$data['ext'],
            'Body'        => $thumb->get($data['ext']),
            'ContentType' => $data['mimetype'],
        ));

    }
}

当我将"sync"作为队列时,一切都很好,我在亚马逊中获得了两个图像(原始图像和调整大小的图像),但在我切换到"beanstlakd"并运行php artisan队列后:听着,我一直收到这个错误:

Next exception 'AwsS3ExceptionS3Exception' 
  with message 'Error executing "GetObject" 
  on "https://s3.eu-central-1.amazonaws.com/bellated/cd05ec14f7a19047828d7ed79d192ee3.jpg";
 AWS HTTP error:  
 Client error: 404 NoSuchKey 
 (client): The specified key does not exist. - 
  <?xml version="1.0" encoding="UTF-8"?>
    <Error>
      <Code>NoSuchKey</Code>
      <Message>The specified key does not exist.</Message>
      <Key>cd05ec14f7a19047828d7ed79d192ee3.jpg</Key>
      <RequestId>9390AD2904820C3E</RequestId> 
      <HostId>
        nZK1ivZn3bs6xy0S/tGe+A7yoZgKKccLpUDObKuwS2Zmi8LXUgFI5JpkQWCkwchCw6tgW7jyvGE=
      </HostId>
    </Error>'
  in /home/vagrant/Code/laravel/vendor/aws/aws-sdk-php/src/WrappedHttpHandler.php:152

有什么想法可能导致这种情况,或者我该如何处理?

看起来您正在将s3键设置为文件名,这可能会让您感到悲伤。

    $s3->putObject(array(
        'Bucket'      => 'bellated',
        'Key'         => $data['hash'].'_100x100.'.$data['ext'],
        'Body'        => $thumb->get($data['ext']),
        'ContentType' => $data['mimetype'],
    ));

这个错误让我这样想。

Client error: 404 NoSuchKey 
(client): The specified key does not exist. - 
<Key>cd05ec14f7a19047828d7ed79d192ee3.jpg</Key>

总的来说,看起来你做这件事很艰难。我不知道如何让你的代码工作,但Laravel做了很多你想做的事情。

以下是我如何做到你想做的事情。

你需要设置你的环境。

.env

    S3_KEY=MYKEYMYKEYMYKEYMYKEY
    S3_SECRET=MYSECRETMYSECRETMYSECRETMYSECRETMYSECRET
    S3_REGION=us-east-1
    S3_BUCKET=bucketname

config/files系统.php

    <?php
    return [
        'default' => 'local',
        'cloud' => 's3',
        'disks' => [
            'local' => [
                'driver' => 'local',
                'root'   => storage_path().'/app',
            ],
        's3' => [
            'driver' => 's3',
            'key'    => env('S3_KEY'),
            'secret' => env('S3_SECRET'),
            'region' => env('S3_REGION'),
            'bucket' => env('S3_BUCKET'),
        ],
        ],
    ];

routes.php快速测试

    Route::get('s3',function(){
        $success = Storage::disk('s3')->put('hello.txt','hello');
        return ($success)?'Yeay!':'Boo Hoo';
    });

我知道这是一个文本文件,但它是一样的。

我将如何处理排队是通过使用Laravel的工作(它过去是命令)。

在终端上键入将生成app/Jobs/NewJob.php文件的类型。

php artisan make:job NewJob --queued

这样安排你的工作。

NewJob.php

    <?php
    namespace AppJobs;
    use ...;
    class NewJob extends Job implements SelfHandling, ShouldQueue
    {
        public $content;
        public $path;
        use InteractsWithQueue, SerializesModels;
        public function __construct($content, $path)
        {
            $this->content = $content;
            $this->path = $path;
        }
        public function handle()
        {
            Storage::disk('s3')->put($this->path,$this->content)
        }
    }

你的控制器类似于

    <?php
    namespace AppHttpControllers;
    use ...;
    class ImageController extends Controller
    {
        public function sendImage($content, $path)
        {
            $this->dispatch(new NewJob($content, $path));
        }
    }

最新更新