php - 如何在 Laravel 中构建图像上传对象并附加到请求
问题描述
我正在尝试构建图像上传对象并附加到 Laravel 中的请求。
我目前有一个中间件,它拦截请求并检查其中是否有 base64 图像字符串,如果有,它将其转换为图像对象并将其附加回请求。
我未能成功地将转换后的图像附加到请求中,作为一个实例,Illuminate\Http\UploadedFile
我尝试了一些我发现的最接近的事情,UploadedFile::fake()->image('avatar.jpg');
但是我如何使用自己的 base64 转换后的图像而不是生成假图像来查看UploadedFile Api我想不出一个解决方案。
这就是我到目前为止所拥有的
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\UploadedFile;
class Base64EncodedImageHandler
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->has('photos')) {
$validator = Validator::make($request->all(), [
'photos' => 'nullable|array|filled',
'photos.*' => 'required_unless:photos,'.null.'|image',
]);
if ($validator->fails()) {
$images = collect($request->input('photos'))->map(function ($item, $key) {
if (preg_match('/^data:image\/(\w+);base64,/', $item)) {
$data = substr($item, strpos($item, ',') + 1);
$data = base64_decode($data);
// Testing to see if the image decoding worked
// Storage::disk('local')->put("public/test/".uniqid().".png", $data);
// Build image object
return $data;
}
return $item;
});
$request = $request->merge(['photos' => $images]);
}
// Dumping request object here
dd($request);
}
return $next($request);
}
}
根据我得到的答案,我能够实现我的最初目标
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\UploadedFile;
class Base64EncodedImageHandler
{
/**
* Handle an incoming request.
*
* @author Sayra
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// Add an additional method
$request::macro('setConvertedFiles', function ($files) {
$this->convertedFiles = $files;
return $this;
});
if ($request->has('portrait')) {
$images = collect($request->input('portrait'))->map(function ($item, $key) {
if (preg_match('/^data:image\/(\w+);base64,/', $item)) {
$item = substr($item, strpos($item, ',') + 1);
$image = base64_decode($item);
$path = 'public/test/';
$name = uniqid();
$extension = '.jpg';
// Store converted file
if (Storage::put($path.$name, $image)){
return new UploadedFile(storage_path('app/').$path.$name, $name.$extension, 'image/jpeg');
}
}
})->all();
// Added base64 converted files to request, clear base64 params
$photos = $request->photos? $request->photos : [];
$merge = array_merge($photos, $images);
$request->setConvertedFiles(['photos' => $merge]);
$request->merge(['photos' => $merge]);
$request->merge(['portrait' => []]);
// the isValid() method fails as the file was not a direct upload
dd($request->file('photos.0')->isValid(),$request->file('photos'),$request);
}
return $next($request);
}
}
我当前唯一的问题是,当isValid
或被is_uploaded_file()
调用时,图像被视为无效图像,我想正确伪造图像上传,以便 base64 转换后的图像能够正常工作并经历与普通图像相同的过程。谢谢。
解决方案
您可以尝试Symfony\Component\HttpFoundation\File\UploadedFile
创建图像对象(您应该首先将 base64 文件保存在临时位置,因为UploadedFile
需要路径)。然后在你的Base64EncodedImageHandler
使用 trait 中Illuminate\Http\Concerns\InteractsWithInput
。
你将需要这个方法:protected function convertUploadedFiles(array $files)
它接受 symfony UploadedFile 的数组。这将使Illuminate\Http\UploadedFile
对象。现在,当您说$request->merge(['photos' => $images])
您的“照片”将是您可以操作的 UploadedFile 对象数组时。
我不确定,但也许你的$request->file()
会仍然是空的。如果这是真的,您可以创建新请求,用原始请求中的所有其他数据填充它,但对于文件,请提供转换后的 UploadedFile 数组。
还要检查这个https://github.com/laravel/framework/issues/10791#issuecomment-213529251
他们正在使用自定义FormRequest
特征来覆盖->all()
方法。您可以尝试使用相同的方法,->allFiles()
甚至覆盖$files
属性。请记住它接受FileBag
,而不是array
推荐阅读
- performance - 步进负载在最后一个蝗虫版本 (2.4.3) 中有效吗?
- ecmascript-6 - CasperJS 和 PhantomJS 意外令牌'const'
- java - 背压不适用于 groupBy 运算符
- python - 按键均匀分布字典列表
- haskell - 如何定义具有构造函数 Times | 的数据类型 Expr 加 | Number 其中 Number 可以是 Haskell 中任何类型的 Number(Int、Double 等)?
- javascript - UTF-8 或“İ”字符未显示或未呈现
- html - 如何使用 REST API 中的 PUT 方法上传文件?
- microprofile - 无法使用 quarkus-microprofile restclient 对代理进行身份验证
- machine-learning - 使用模型的预测分数作为运动质量评估器
- linux - 在 2 条分隔线之间操作多行(如果不存在则追加,否则替换)