-
將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 ], 在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ò)了
- 修改頭像上傳邏輯,增加了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();
}
}