laravel - 使用 laravel 作业处理图像上传时无法解决的依赖关系
问题描述
每个上传的图像都会为不同的屏幕再创建四个图像,然后传输到 Digital Ocean 上的一个空间。所以非常耗时。因此我想使用 Laravel Job 功能。这是它现在的样子:
图像控制器:
public function uploadMultiple($vehicle_id, Request $request)
{
$this->setVehicle($vehicle_id);
$this->validate($request, [
'images' => 'required',
'images.*' => 'image'
]);
foreach ($request->images as $image){
$this->uploadSingleImage($image);
}
\Alert::success('Bilder wurden hochgeladen')->flash();
return redirect()->back();
}
protected function uploadSingleImage(UploadedFile $image)
{
VehicleImageUploaderJob::dispatch($this->getVehicle());
}
VehicleImageUploader工作:
public function handle(UploadedFile $image)
{
$disk = FilesystemHelper::getDisk('producerData');
$originalName = basename($image->getClientOriginalName(), '.'.$image->getClientOriginalExtension());
$extension = $image->getClientOriginalExtension();
$dbImage = new Image();
// Store image in original size
$path = $image->storeAs(
'producers/' . $this->getVehicle()->producer->id . '/vehicles/' . $this->getVehicle()->id, // Folder or Directory
$image->getClientOriginalName(), // File Name
$disk // Disk
);
Storage::disk($disk)->setVisibility($path, 'public');
$dbImage->original = $path;
$dbImage->disk = $disk;
$file = ImageManipulator::make($image);
foreach(config('images.vehicles.formats') as $format => $values){
$file->backup();
$fileName = $originalName . '-' . str_random(6) . '-' . $values['width'] . 'x' . $values['height'] . '.' . $extension;
if($format === 'thumbnail'){
$file->fit($values['width'],$values['height'])
->save();
} else {
$file->fit($values['width'], $values['height'], function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save();
}
$path = $image->storeAs(
'producers/' . $this->getVehicle()->producer->id . '/vehicles/' . $this->getVehicle()->id, // Folder or Directory
$fileName, // File Name
$disk // Disk
);
Storage::disk($disk)->setVisibility($path, 'public');
$dbImage->{$format} = $path;
$file->reset();
}
$dbImage->save();
$this->getVehicle()->images()->attach($dbImage->id);
$this->getVehicle()->save();
}
不幸的是,每次我想上传图像时都会出错(当前队列驱动程序是“同步”): 类 Symfony\Component\HttpFoundation\File\UploadedFile 中的 Unresolvable dependency resolve [Parameter #0 [ string $path ]]
也许是因为我应该通过图像而不是车辆。在构造函数中需要车辆,在句柄方法中需要图像。但是当我传入图像时,它会抛出一个错误,说它需要一个 Vehicle 的实例。
解决方案
问题是 UploadedFile(你从上传请求中得到的)不是可序列化的,因此不能被作业处理。所以我不得不创建一个新的模型+表来临时存储图像。
图像的方式如下:
- 本地存储为文件
- 创建临时模型的新实例
- 将此模型传递给工作
- 重新创建 UploadedFile 类型的图像并处理图像(创建四个分辨率并将其加载到数字海洋)
- 删除本地文件
- 删除临时模型
新模式:
use App\DBEntities\MasterEntity;
class VehicleImageForJob extends MasterEntity
{
protected $guarded = ['id'];
}
新表:
class CreateVehicleImageForJobsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('vehicle_image_for_jobs', function (Blueprint $table) {
$table->increments('id');
$table->string('file');
$table->string('mime_type');
$table->string('original_name');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('vehicle_image_for_jobs');
}
}
filesystem.php 中的新磁盘:
'vehicle_image_temp' => [
'driver' => 'local',
'root' => storage_path('app/vehicle_images/temp')
]
修改后的控制器:
protected function uploadSingleImage(UploadedFile $image)
{
$disk = 'vehicle_image_temp';
$path = $image->store("/", [
'disk' => $disk
]);
$vehicleImageForJob = VehicleImageForJob::create([
'file' => $path,
'mime_type' => $image->getMimeType(),
'original_name' => $image->getClientOriginalName()
]);
VehicleImageUploaderJob::dispatch($vehicleImageForJob, $this->getVehicle());
}
修改工作:
class VehicleImageUploaderJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $vehicle;
protected $image;
protected $disk = 'vehicle_image_temp';
/**
* VehicleImageUploaderJob constructor.
* @param VehicleImageForJob $image
* @param Vehicle $vehicle
*/
public function __construct(VehicleImageForJob $image, Vehicle $vehicle)
{
$this->vehicle = $vehicle;
$this->image = $image;
}
/**
* @param UploadedFile $image
* @throws \Exception
*/
public function handle()
{
$image = new UploadedFile(storage_path("app/vehicle_images/temp/{$this->image->file}"),
$this->image->original_name,
$this->image->mime_type,
null,
null,
true
);
$disk = FilesystemHelper::getDisk('producerData');
$originalName = basename($image->getClientOriginalName(), '.'.$image->getClientOriginalExtension());
$extension = $image->getClientOriginalExtension();
$dbImage = new Image();
// Store image in original size
$path = $image->storeAs(
'producers/' . $this->getVehicle()->producer->id . '/vehicles/' . $this->getVehicle()->id, // Folder or Directory
$image->getClientOriginalName(), // File Name
$disk // Disk
);
Storage::disk($disk)->setVisibility($path, 'public');
$dbImage->original = $path;
$dbImage->disk = $disk;
$file = ImageManipulator::make($image);
foreach(config('images.vehicles.formats') as $format => $values){
$file->backup();
$fileName = $originalName . '-' . str_random(6) . '-' . $values['width'] . 'x' . $values['height'] . '.' . $extension;
if($format === 'thumbnail'){
$file->fit($values['width'],$values['height'])
->save();
} else {
$file->fit($values['width'], $values['height'], function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save();
}
$path = $image->storeAs(
'producers/' . $this->getVehicle()->producer->id . '/vehicles/' . $this->getVehicle()->id, // Folder or Directory
$fileName, // File Name
$disk // Disk
);
Storage::disk($disk)->setVisibility($path, 'public');
$dbImage->{$format} = $path;
$file->reset();
}
$dbImage->save();
$this->getVehicle()->images()->attach($dbImage->id);
$this->getVehicle()->save();
Storage::disk($this->disk)->delete($this->image->file);
$this->image->delete();
}
protected function getVehicle(): Vehicle
{
if($this->vehicle instanceof Vehicle){
return $this->vehicle;
} else {
throw new \Exception("Vehicle not set on ImageUploaderJob");
}
}
}
推荐阅读
- c++ - VBO必须在VAO之后绑定
- php - 验证 WordPress 上的 textarea 字段
- ruby-on-rails - 简单的 Rails 嵌套关联 where 子句的问题
- javascript - 在动态路由更改的情况下,历史推送 url 不会再次重新初始化组件
- vba - 将 IST 转换为 AEST 的宏
- vba - Excel VBA:自动单击并从网站打开文件
- ruby-on-rails - 在我的 Pundit 政策中使用范围(Rails 5)
- android - 具有自定义背景和三角形的微调器
- css - 跳转到 Visual Studio Code 中的 ID 或类选择器
- autohotkey - AHK 脚本的工具键