UploadController.php 12.1 KB
<?php
/**
+-----------------------------------------------------------------------------------------------------------------------
 * 上传基类:
+----------------------------------------------------------------------------------------------------------------------
 *
 * PHP version 7
 *
 * @category  App\Http\Controllers\Service
 * @package   App\Http\Controllers\Service
 * @author    Richer <yangzi1028@163.com>
 * @date      2020年11月13日 01:26:09
 * @copyright 2021-2022 Richer (http://www.Richer.com/)
 * @license   http://www.Richer.com/ License
 * @link      http://www.Richer.com/
 */
namespace App\Http\Controllers\Service;

use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\Facades\Image;
use Ramsey\Uuid\Uuid;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\File;

// 引入鉴权类
use Qiniu\Auth;
// 引入上传类
use Qiniu\Storage\UploadManager;

/**
 * Class UploadController
 *
 * @category  App\Http\Controllers\Service
 * @package   App\Http\Controllers\Service
 * @author    Richer <yangzi1028@163.com>
 * @date      2020年11月13日 01:26:09
 * @copyright 2021-2022 Richer (http://www.Richer.com/)
 * @license   http://www.Richer.com/ License
 * @link      http://www.Richer.com/
 */

class UploadController extends Controller
{

    protected $file_size_max = 10 * 1024 * 1024;// 上传文件最大为10M

    protected $message = 'success';

    /**
     * 上传
     *
     * @param Request $request
     * @param string $field
     * @param string $filetype
     *
     * @return array
     * @throws \Exception
     */
    public function upload($request, $field = 'file', $filetype = 'image')
    {
        Log::info("请求");
        Log::info($request->file($field));
        Log::info($request->ceshi);

        //文件获取:取特定的参数名,可以改为配置参数
        $files = $request->file($field) ?? $request->ceshi;
        //无上传文件抛出错误信息
        if (empty($files)) {
            return [
                'code'  => Response::HTTP_BAD_REQUEST,
                'data'  => null,
                'msg'   => '文件不存在!'
            ];
        }

        // 验证文件是否为正确的文件类型类型
        if (!$verify = $this->verifyFile($files, $filetype)) {
            return [
                'code'  => Response::HTTP_UNPROCESSABLE_ENTITY,
                'data'  => null,
                'msg'   => $this->message,
            ];
        }

        // 上传文件到七牛云:可以根据系统配置设置上传到七牛云还是本地
        if (!$return =  $this->uploadToLocalServer($files, $filetype)) {
            return [
                'code'  => Response::HTTP_BAD_REQUEST,
                'data'  => null,
                'msg'   => $this->message,
            ];
        }
        // 上传成功,返回文件信息和路径
        return ['code' => 0, 'data' => $return, 'msg' => 'success'];
    }

    /**
     * 检测上传的文件是否有效的文件类型
     *
     * @param   $file
     * @param string $filetype
     * @return bool
     */
    public function verifyFile($file, $filetype = 'image')
    {

        if (is_array($file)) {
            foreach ($file as $key => $vo) {
                if (is_array($vo)) {
                    return $this->verifyFile($vo, $filetype);
                } else {
                    if (!$isValid = $vo->isValid()) {
                        $this->message ='第'.($key+1) .'个文件无效!';
                        return false;
                    }

                }

                // 判断文件类型
                if (!$this->verifyFileType($vo, $key, $filetype)) {
                    return false;
                }

                if (!$this->verifyFileSize($vo, $key)) {
                    return false;
                }
                // return $this->verifyFile($vo, $filetype);
            }
        } else {
            if (!$isValid = $file->isValid()) {
                $this->message ='文件无效!';
                return false;
            }

            // 判断文件类型
            if (!$this->verifyFileType($file, 0, $filetype)) {
                return false;
            }

            // 判断文件大小
            if (!$this->verifyFileSize($file)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 验证文件大小是否正确
     *
     * @param $file
     * @param int $index
     * @param string $filetype
     *
     * @return bool
     */
    public function verifyFileType($file, $index = 0, $filetype = 'image')
    {
        // 如果是全部的文件类型,则不进行类型的判断
        if ($filetype === 'all') {
            return true;
        }

        $fileMimeType = 'image/';
        // 上传文件的类型
        $mimeType = $file->getClientMimeType();
        // 上传文件的原始文件名
        $originalName = $file->getClientOriginalName();

        switch ($filetype) {
            case 'image':
                if (!Str::startsWith($mimeType, $fileMimeType) && !is_image($originalName)) {
                    $this->message ='第'.($index+1) .'个文件不是有效的图片文件!';
                    return false;
                }
                break;
            case 'video':
                $fileMimeType = 'video/';
                if (!Str::startsWith($mimeType, $fileMimeType) && !is_video($originalName)) {
                    $this->message ='第'.($index+1) .'个文件不是有效的视频文件!';
                    return false;
                }
                break;
        }
        return true;
    }

    /**
     * 验证文件大小是否正确
     *
     * @param $file
     * @param int $index
     * @return bool
     */
    public function verifyFileSize($file, $index = 0)
    {
//        if ($size = $file->getClientSize() > $this->file_size_max) { Laravel5.5
        if ($size = $file->getSize() > $this->file_size_max) { // Laravel 8.0
            $this->message ='第'.($index+1) .'个文件大小超过' .$this->file_size_max /(1024*1024) .'M!';
            return false;
        }

        return true;
    }

    /**
     * 上传文件到七牛云服务器
     * 1、根据文件的类型,指定不同的目录
     * 2、如果是文件数组,需要递归调用方法进行上传
     * 3、上传成功后,需要换文件信息保存到本地数据库中,方便前端调用
     *
     * @param $file
     * @param string $filetype
     * @return array|bool
     * @throws \Exception
     */
    public function uploadToQiniu($file, $filetype = 'image')
    {
        $return = [];
        $dir = 'images';
        if ($filetype == 'video') {
            $dir = 'videos';
        } elseif ($filetype == 'all') {
            $dir = 'files';
        }
        if (is_array($file)) {
            foreach ($file as $vo) {
                // 上传文件到七牛云
                $return[] =  $this->uploadToQiniu($vo, $filetype);
            }
        } else {
            // 获取原始文件名
            $original_name  = $file->getClientOriginalName();
            // 获取后缀名
            $extension      = $file->extension();
            // 生成新的文件名
            $name           = Uuid::uuid1(). '.' . $extension;

            if (request('is_original_name') == 1) {
                $name = $original_name;
            }
            $return['name']          = $name;
            $return['original_name'] = $original_name;
            // 存储图片路径
            $file_name = '/'.$dir.'/' . date('Ymd') .'/'.$name;

            if (!$response_upload = \Storage::disk('qiniu')->put($file_name, fopen($file, 'r+'))) {
                $this->message ='上传到七牛云失败';
                return false;
            }

            $full_path = config('filesystems.disks.qiniu.host'). $file_name;
            // add By Richer 于 2019年11月29日16:18:42 上传成功后,将图片同时保存到本地,将文件的信息保存到本地,方便前端调用

//
//            $client = new \GuzzleHttp\Client();
//            $response = $client->get('http://clouddn.www.xxx.com/images/20191129/e6b5db40-1285-11ea-a5ae-fdd6f4a9db1b.jpeg');
//            \Log::info(json_encode($response));
//            $content = json_decode($response->getBody()->getContents());
//            \Log::info(json_encode($content));

            if (is_image($file_name)) {
                $image_size = getimagesize($file);
                //StoreFileAfterUploadToQiniu::dispatch($name, $original_name, $file_name, $full_path, $image_size, $extension, filesize($file));
            }
            $return['path']     = $file_name;
            $return['full_path'] = $full_path;
        }
        return $return;
    }


    /**
     * 上传文件到本地服务器
     *
     * @param $file
     * @param string $filetype
     * @return array
     * @throws \Exception
     */
    public function uploadToLocalServer($file, $filetype = 'image')
    {
        //获取存入数据库的相对路径
        $public_path = '/storage/upload/' . date('Ymd');
        $storage_path = '/app/public/upload/' . date('Ymd');
        $return = [];

        //服务器真是路径
        if (!File::exists($real_path = storage_path($storage_path))) {
            File::makeDirectory($real_path, 755, true, true);
        }

        if (is_array($file)) {
            foreach ($file as $vo) {
                // 上传文件到七牛云
                $return[] =  $this->uploadToLocalServer($vo, $filetype);
            }
        } else {
            // 获取原始文件名
            $original_name = $file->getClientOriginalName();
            //临时文件的绝对路径
            $realPath = $file->getRealPath();
            // 获取后缀名
            $extension = $file->extension();
            //设置文件路径和名称
            $name = Uuid::uuid1();
            $return['name']          = $name;
            $return['path']          = date('Ymd') .'/' .$name. '.' . $extension;
            $return['original_name'] = $original_name;

            $result = Storage::disk($filetype)->put($return['path'], file_get_contents($realPath)); // 文件名称 , 内容
            if ($result) {
                $return['full_path'] = Storage::disk($filetype)->url($return['path']);
                return $return;
            } else {
                return false;
            }

            $image = Image::make($file)->save($real_path . '/' . $name . '.' . $extension);

            $path = $public_path . '/' . $name . '.' . $extension;
            if (request()->filled('width') || request()->filled('height')) {
                $image->resize(
                    request()->input('width'),
                    request()->input('height'),
                    function ($constraint) {
                        $constraint->aspectRatio();
                        $constraint->upsize();
                    }
                );

                $path = $public_path . '/' . $name . '.thumb.' . $extension;
                $image->save($real_path . '/' . $name . '.thumb.' . $extension);
            }
            $return['path']     = $path;
            $return['full_path'] = config('app.url').$path;
        }

        return $return;
    }

//    /**
//     * 上传图片
//     *
//     * @param Request $request
//     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|Response
//     */
//    public function img($originalName, $realPath, $path)
//    {
//        Storage::disk('img')->put($originalName, file_get_contents($realPath)); // 文件名称 , 内容
//            $file = $request->file('file'); // 获取上传的文件
//
//// 获取文件相关信息
//
//            $originalName = $file->getClientOriginalName(); // 文件原名
//
//            $realPath = $file->getRealPath(); //临时文件的绝对路径
//
//
//            return response(['message' => '上传成功', 'url' => '/uploads/img/'.$originalName], 201);
//
//        } else {
//            return response(['message' => '请重新上传'], 400);
//
//        }
//
//    }
}