使用summerblue/administrator或者FrozenNode/Laravel-Administrator這個(gè)包如何將后臺(tái)頭像上傳改為傳到阿里云OSS(方法比較笨,有待測(cè)試和優(yōu)化)?

  1. 將config/administrator/users.php里的avatar對(duì)應(yīng)的目錄注釋掉,換成如下這樣

        'avatar' => [
        'title' => '用戶(hù)頭像',
         // 設(shè)置表單條目的類(lèi)型,默認(rèn)的 type 是 input
         'type' => 'image',
    
         // 圖片上傳必須設(shè)置圖片存放路徑
         //'location' => public_path() . '/uploads/images/avatars/',
         'location' => 'https://xxx.xxx.aliyuncs.com/uploads/images/avatars/'. date('Ymd') . DIRECTORY_SEPARATOR
     ],
    
  2. 在vendor下找到summer大神的這個(gè)包(建議fork一份在修改)
    大部分修改都在/vendor/summerblue/administrator/src/controllers/AdminController.php這個(gè)文件里,首先先把判斷l(xiāng)ocation是不是目錄的方法改掉,文件位置(如圖)下的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號(hào)修改
        $statusDir = is_dir($value);
        $statusOss = strpos($value,"aliyuncs.com");
        if($statusDir || $statusOss){
            return true;
        }else{
            return false;
        }
    }

加了一個(gè)簡(jiǎn)單的判斷,如果目錄是aliyuncs的話,也返回true, 這樣這里就不報(bào)錯(cuò)了

  1. 修改頭像上傳邏輯,增加了oss判斷邏輯fileUpload()是上傳方法, displayFile()是上傳之后用于顯示圖片的方法,同時(shí)調(diào)用了之前寫(xiě)的ImageUploadHandler.php輔助類(lèi)
 /**
     * 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
        //判斷一下目錄是真實(shí)目錄還是OSS地址,如果是真實(shí)目錄則保持源代碼不變
        $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下用于后面獲取二進(jìn)制數(shù)據(jù)流
            $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()
    {
        //判斷一下目錄是真實(shí)目錄還是OSS地址,如果是真實(shí)目錄則保持源代碼不變
        $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下的圖之后,可以考慮刪掉,這里我沒(méi)有做處理,保留了下來(lái)
            
        }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)
    {
        //存儲(chǔ)文件規(guī)則 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'){
            //封裝函數(shù),裁剪圖片
            $this->reduceSize($file->getRealPath(),$max_width);
        }
        //保存一份到/tmp目錄下,為了后面獲取圖片信息數(shù)據(jù)
        Storage::disk('local')->putFileAs('tmp',new File($file->getRealPath()),$fileName);

        //上傳圖片  $file->getRealPath()獲取真實(shí)文件地址,$file是個(gè)對(duì)象,雖然也能上傳,但是在OSS上會(huì)建立目錄
        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()加一層驗(yàn)證:

    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` 子串開(kāi)頭,那就是從后臺(tái)上傳的,需要補(bǔ)全 URL
            if ( ! starts_with($path, 'http')) {

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

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

這樣就可以了,修改的思路就是確保原代碼不動(dòng),加入oss路徑判斷,以及響應(yīng)結(jié)果格式和原代碼保持一致,這樣改完,如果不想用阿里OSS,直接注釋掉users.php里的location配置,繼續(xù)用服務(wù)器目錄也可以。
這幾段代碼是周五晚上臨時(shí)修改的,很多地方不簡(jiǎn)潔也不嚴(yán)謹(jǐn),也沒(méi)有經(jīng)過(guò)仔細(xì)測(cè)試,總覺(jué)得更好的方法應(yīng)該是不修改作者源碼才對(duì),水平有限,目前還沒(méi)想到好辦法,有點(diǎn)蛋疼。

附錄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)
    {
        //存儲(chǔ)文件規(guī)則 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'){
            //封裝函數(shù),裁剪圖片
            $this->reduceSize($file->getRealPath(),$max_width);
        }
        //上傳圖片  $file->getRealPath()獲取真實(shí)文件地址,$file是個(gè)對(duì)象,雖然也能上傳,但是在OSS上會(huì)建立目錄
        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)
    {
        //存儲(chǔ)文件規(guī)則 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'){
            //封裝函數(shù),裁剪圖片
            $this->reduceSize($file->getRealPath(),$max_width);
        }
        //保存一份到/tmp目錄下,為了后面獲取圖片信息數(shù)據(jù)
        Storage::disk('local')->putFileAs('tmp',new File($file->getRealPath()),$fileName);

        //上傳圖片  $file->getRealPath()獲取真實(shí)文件地址,$file是個(gè)對(duì)象,雖然也能上傳,但是在OSS上會(huì)建立目錄
        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)
    {
        //實(shí)例化, 參數(shù)是文件的磁盤(pán)物理路徑
        $image = Image::make($file_path);

        //調(diào)整大小
        $image->resize($max_width, null, function($constraint){
            // 設(shè)定寬度是 $max_width,高度等比例雙方縮放
            $constraint->aspectRatio();

            // 防止裁圖時(shí)圖片尺寸變大
            $constraint->upsize();
        });

        // 對(duì)圖片修改后進(jìn)行保存
        $image->save();
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容