每个上传的图像为不同的屏幕创建另外四个图像,然后传输到Digital Ocean上的空间。所以这非常耗时。因此,我想使用Laravels Job功能。这就是它现在的样子:
ImageController:
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());
}
车辆图像上传工作:
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类中无法解析的依赖项解析[参数#0 [string $ path]]
也许是因为我应该传递图像而不是车辆。车辆在构造函数中是预期的,而处理方法中的图像是预期的。但是当我传入图像时,它会抛出一个错误,说它需要一个Vehicle实例。
问题是UploadedFile(你从upload-request获得的)是不可序列化的,因此不能由作业处理。所以我不得不创建一个新的模型+表来临时存储图像。
图像的方式如下:
新模式:
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");
}
}
}