-
将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 ],
在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, 这样这里就不报错了
- 修改头像上传逻辑,增加了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();
}
}