【问题标题】:How to build an image upload object and append to request in Laravel如何在 Laravel 中构建图像上传对象并附加到请求
【发布时间】:2020-06-02 08:16:59
【问题描述】:

我正在尝试构建一个图像上传对象并附加到 Laravel 中的请求。

我目前有一个中间件,它拦截请求并检查其中是否有 base64 图像字符串,如果有,它将其转换为图像对象并将其附加回请求。

我未能成功地将转换后的图像作为Illuminate\Http\UploadedFile 的实例附加到请求中通过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);
        }
    }

我当前唯一的问题是,当调用 isValidis_uploaded_file() 时,图像被视为无效图像,我想正确伪造图像上传,以便 base64 转换后的图像能够正常工作并通过相同的处理处理为正常图像。谢谢。

【问题讨论】:

  • 我一直在这条路上,我猜你的前端工程师觉得提交 base64 图像而不是构建一个实际的图像对象对他/她来说很方便?无论如何,我的建议是github.com/hshn/base64-encoded-file 看看这个包,但我建议单独处理 base64 提交,尝试将两者结合起来只会导致无尽的挫败感。 :(

标签: php laravel image


【解决方案1】:

您可以尝试使用Symfony\Component\HttpFoundation\File\UploadedFile 创建图像对象(您应该首先将base64 文件临时保存在某个地方,因为UploadedFile 需要路径)。然后在你的Base64EncodedImageHandler 中使用特征Illuminate\Http\Concerns\InteractsWithInput

你将需要这个方法:protected function convertUploadedFiles(array $files),它接受 symfony UploadedFile 数组。这将使Illuminate\Http\UploadedFile 成为对象。现在,当您说$request-&gt;merge(['photos' =&gt; $images]) 时,您的“照片”将是您可以操作的 UploadedFile 对象数组。

我不确定,但您的$request-&gt;file() 可能仍为空。如果这是真的,您可以创建新请求,用原始请求中的所有其他数据填充它,但对于文件,请提供转换后的 UploadedFile 数组。

也可以查看https://github.com/laravel/framework/issues/10791#issuecomment-213529251 他们正在使用自定义 FormRequest 特征来覆盖 -&gt;all() 方法。您可以尝试对-&gt;allFiles() 进行相同操作,甚至覆盖$files 属性。请记住,它接受FileBag,而不是array

【讨论】:

  • 非常感谢您的回答,我花了一些时间才弄明白,就像您说的那样,$request-&gt;file() 仍然是空的 :( 我试过 $request-&gt;convertedFiles = $images 但它是一个受保护的变量。
  • $request->convertedFiles 它是一个受保护的属性,而不是变量 ;)
猜你喜欢
  • 1970-01-01
  • 2015-04-11
  • 2020-05-20
  • 2019-11-14
  • 2022-01-11
  • 2017-04-11
  • 2015-09-22
  • 1970-01-01
  • 2016-08-11
相关资源
最近更新 更多