使用summerblue/administrator或者FrozenNode/Laravel-Administrator这个包如何将后台头像上传改为传到阿里云OSS(方法比较笨,有待测试和优化)?

  1. 将config/administrator/users.php里的avatar对应的目录注释掉,换成如下这样

        'avatar' => [
        'title' => '用户头像',
         // 设置表单条目的类型,默认的 type 是 input
         'type' => 'image',
    
         // 图片上传必须设置图片存放路径
         //'location' => public_path() . '/uploads/images/avatars/',
         'location' => 'https://xxx.xxx.aliyuncs.com/uploads/images/avatars/'. date('Ymd') . DIRECTORY_SEPARATOR
     ],
    
  2. 在vendor下找到summer大神的这个包(建议fork一份在修改)
    大部分修改都在/vendor/summerblue/administrator/src/controllers/AdminController.php这个文件里,首先先把判断location是不是目录的方法改掉,文件位置(如图)下的validateDirectory()方法

~/Code/larabbs/vendor/summerblue/administrator/src/Frozennode/Administrator/Validator.php
    /**
     * Validates that an item is a directory.
     */
    public function validateDirectory($attribute, $value, $parameters)
    {
        //return is_dir($value); //于11月2号修改
        $statusDir = is_dir($value);
        $statusOss = strpos($value,"aliyuncs.com");
        if($statusDir || $statusOss){
            return true;
        }else{
            return false;
        }
    }

加了一个简单的判断,如果目录是aliyuncs的话,也返回true, 这样这里就不报错了

  1. 修改头像上传逻辑,增加了oss判断逻辑fileUpload()是上传方法, displayFile()是上传之后用于显示图片的方法,同时调用了之前写的ImageUploadHandler.php辅助类
 /**
     * The POST method that runs when a user uploads a file on a file field.
     *
     * @param string $modelName
     * @param string $fieldName
     * Request $request是lpf新加的
     * @return JSON
     */
    public function fileUpload($modelName, $fieldName, Request $request, ImageUploadHandler $uploader)
    {
        //lpf 2018/11/02 Edit
        //判断一下目录是真实目录还是OSS地址,如果是真实目录则保持源代码不变
        $path = config('administrator.users.edit_fields.avatar.location');

        if(is_dir($path)){
            //dd($modelName); //users
            //dd($fieldName); //avatar
            $fieldFactory = app('admin_field_factory');

            //get the model and the field object
            $field = $fieldFactory->findField($fieldName);

            return response()->JSON($field->doUpload());
        }else{
            /*
                 array:5 [
                    "errors" => []
                    "path" => "/home/lpf/Code/larabbs/public/uploads/images/avatars/kpAodaQyzmjevze0wwUJTgp1rMzXEHWr.jpeg"
                    "filename" => "kpAodaQyzmjevze0wwUJTgp1rMzXEHWr.jpeg"
                    "original_name" => "timg (2).jpeg"
                    "resizes" => []
                    ]
             */
            //存一份到storage/tmp下用于后面获取二进制数据流
            $result = $uploader->saveAdmin($request->file('file'),'avatars',$modelName, 362);

            return response()->JSON($result);
        }
    }
 /**
     * The GET method that displays a file field's file.
     *
     * @edit By lpf
     * @return Image / File
     */
    public function displayFile()
    {
        //判断一下目录是真实目录还是OSS地址,如果是真实目录则保持源代码不变
        $pathConfig = config('administrator.users.edit_fields.avatar.location');

        //get the stored path of the original
        $path = $this->request->input('path');

        if(!is_dir($pathConfig)){
            $tmpFileName = basename($path);

            $pathTmp = storage_path("app/tmp/{$tmpFileName}");
            $data = File::get($pathTmp);
            $file = new SFile($pathTmp);
            
            //使用完tmp下的图之后,可以考虑删掉,这里我没有做处理,保留了下来
            
        }else{
            $data = File::get($path);
            $file = new SFile($path);

        }

        $mimeType   = $file->getMimeType();
        $size       = $file->getSize();
        $fileName   = $file->getFilename();

        $headers = array(
            'Content-Type'        => $mimeType,
            'Content-Length'      => $size,
            'Content-Disposition' => 'attachment; filename="'.$fileName.'"',
        );


        return response()->make($data, 200, $headers);
    }
    public function saveAdmin($file,$folder,$file_prefix = null, $max_width = false)
    {
        //存储文件规则 uploads/images/avatars/20180808/
        $folderName = "uploads/images/$folder/".date('Ymd');

        //获取文件的后缀名
        $extension  = strtolower($file->getClientOriginalExtension()) ?? 'jpg';

        //判断图片是否正确
        if(!getimagesize($file) || !in_array($extension,$this->allowed_ext)){
            return false;
        }

        $fileName = $file_prefix . '_' . time() . '_' .str_random(10) . '.' . $extension;

        //裁剪图片
        if($max_width && $extension != 'gif'){
            //封装函数,裁剪图片
            $this->reduceSize($file->getRealPath(),$max_width);
        }
        //保存一份到/tmp目录下,为了后面获取图片信息数据
        Storage::disk('local')->putFileAs('tmp',new File($file->getRealPath()),$fileName);

        //上传图片  $file->getRealPath()获取真实文件地址,$file是个对象,虽然也能上传,但是在OSS上会建立目录
        Storage::disk('oss-public')->putFileAs($folderName,new File($file->getRealPath()),$fileName);



        return [
            'errors' => [],
            'filename' => $fileName,
            'original_name' => $file->getClientOriginalName(),
            'resizes' => [],
            'path' =>  config('app.ali_endpoint') . DIRECTORY_SEPARATOR . "$folderName/$fileName"
        ];

    }

然后再将Model下的User.php中的setAvatarAttribute()加一层验证:

    public function setAvatarAttribute($path)
    {
        $dir_path = config('administrator.users.edit_fields.avatar.location');


        //修改这块逻辑
        if(!is_dir($dir_path)){
            //oss上传
            $this->attributes['avatar'] = $dir_path.$path;
        }else{
            // 如果不是 `http` 子串开头,那就是从后台上传的,需要补全 URL
            if ( ! starts_with($path, 'http')) {

                // 拼接完整的 URL
                $path = config('app.url') . "/uploads/images/avatars/$path";
            }

            $this->attributes['avatar'] = $path;
        }
    }

这样就可以了,修改的思路就是确保原代码不动,加入oss路径判断,以及响应结果格式和原代码保持一致,这样改完,如果不想用阿里OSS,直接注释掉users.php里的location配置,继续用服务器目录也可以。
这几段代码是周五晚上临时修改的,很多地方不简洁也不严谨,也没有经过仔细测试,总觉得更好的方法应该是不修改作者源码才对,水平有限,目前还没想到好办法,有点蛋疼。

附录ImageUploadHandler.php代码

<?php
/**
 * Created by PhpStorm.
 * User: root
 * Date: 18-8-21
 * Time: 下午2:10
 */
namespace App\Handlers;

use Illuminate\Http\File;
use Illuminate\Support\Facades\Storage;
use Image;

class ImageUploadHandler
{
    /**
     *
     * File move(string $directory, string $name = null)
        Moves the file to a new location.

        Parameters
        string  $directory  The destination folder
        string  $name   The new file name
        Return Value
        File    A File object representing the new file
        Exceptions
        FileException   if, for any reason, the file could not have been moved
     */
    //只允许以下后缀名的图片文件上传
    protected $allowed_ext = ['png','jpg','gif','jpeg'];


    public function save($file,$folder,$file_prefix = null, $max_width = false)
    {
        //存储文件规则 uploads/images/avatars/20180808/
        $folderName = "uploads/images/$folder/".date('Ymd');

        //获取文件的后缀名
        $extension  = strtolower($file->getClientOriginalExtension()) ?? 'jpg';

        //判断图片是否正确
        if(!getimagesize($file) || !in_array($extension,$this->allowed_ext)){
            return false;
        }

        $fileName = $file_prefix . '_' . time() . '_' .str_random(10) . '.' . $extension;

        //裁剪图片
        if($max_width && $extension != 'gif'){
            //封装函数,裁剪图片
            $this->reduceSize($file->getRealPath(),$max_width);
        }
        //上传图片  $file->getRealPath()获取真实文件地址,$file是个对象,虽然也能上传,但是在OSS上会建立目录
        Storage::disk('oss-public')->putFileAs($folderName,new File($file->getRealPath()),$fileName);



        return [
            'path' =>  config('app.ali_endpoint') . DIRECTORY_SEPARATOR . "$folderName/$fileName"
        ];

    }

    public function saveAdmin($file,$folder,$file_prefix = null, $max_width = false)
    {
        //存储文件规则 uploads/images/avatars/20180808/
        $folderName = "uploads/images/$folder/".date('Ymd');

        //获取文件的后缀名
        $extension  = strtolower($file->getClientOriginalExtension()) ?? 'jpg';

        //判断图片是否正确
        if(!getimagesize($file) || !in_array($extension,$this->allowed_ext)){
            return false;
        }

        $fileName = $file_prefix . '_' . time() . '_' .str_random(10) . '.' . $extension;

        //裁剪图片
        if($max_width && $extension != 'gif'){
            //封装函数,裁剪图片
            $this->reduceSize($file->getRealPath(),$max_width);
        }
        //保存一份到/tmp目录下,为了后面获取图片信息数据
        Storage::disk('local')->putFileAs('tmp',new File($file->getRealPath()),$fileName);

        //上传图片  $file->getRealPath()获取真实文件地址,$file是个对象,虽然也能上传,但是在OSS上会建立目录
        Storage::disk('oss-public')->putFileAs($folderName,new File($file->getRealPath()),$fileName);



        return [
            'errors' => [],
            'filename' => $fileName,
            'original_name' => $file->getClientOriginalName(),
            'resizes' => [],
            'path' =>  config('app.ali_endpoint') . DIRECTORY_SEPARATOR . "$folderName/$fileName"
        ];

    }

    public function reduceSize($file_path, $max_width)
    {
        //实例化, 参数是文件的磁盘物理路径
        $image = Image::make($file_path);

        //调整大小
        $image->resize($max_width, null, function($constraint){
            // 设定宽度是 $max_width,高度等比例双方缩放
            $constraint->aspectRatio();

            // 防止裁图时图片尺寸变大
            $constraint->upsize();
        });

        // 对图片修改后进行保存
        $image->save();
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容