【LSky Pro 改造】为兰空新增随机图片 API
编辑
105
2025-08-01
最近在玩
LSky Pro图床,感觉体验还不错。不过,为了满足我的一些“使用习惯,我还是忍不住自己动手捣鼓了一番 😏
LSky Pro默认是没有随机图片功能的,所以这次的目标是:让图床支持随机图片的获取方式。
🚧 实现步骤
1. 新建控制器
在路径 app/Http/Controllers/Api/V1/ 下新建一个控制器:RandomImageController.php
直接贴完整代码如下:
<?php
namespace App\Http\Controllers\Api\V1;
use App\Http\Controllers\Controller;
use App\Models\Image;
use App\Models\Strategy;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
class RandomImageController extends Controller
{
/**
* 随机获取用户的一张图片(不限制存储策略)
* 支持参数:
* - type: 文件类型,如 png, jpg, mp4
* - format: 返回格式 json/url/raw
* 支持三种返回方式:
* - 默认:返回图片信息JSON
* - ?format=url:返回图片URL链接
* - ?format=raw:直接返回图片内容
*/
public function random(Request $request): Response
{
$format = $request->query('format', 'json'); // json, url, raw
$type = $request->query('type'); // 文件扩展名,如:jpg, png, mp4
/** @var User $user */
$user = Auth::user();
$query = $user->images();
// 如果指定了文件类型,添加筛选条件
if ($type) {
$query->where('extension', strtolower($type));
}
// 随机获取用户的一张图片
$image = $query->inRandomOrder()->first();
if (!$image) {
if ($type) {
return $this->fail("没有找到 {$type} 类型的文件");
}
return $this->fail('没有找到图片');
}
return $this->formatImageResponse($image, $format);
}
/**
* 根据存储策略ID随机获取一张图片
* 支持三种返回方式:
* - 默认:返回图片信息JSON
* - ?format=url:返回图片URL链接
* - ?format=raw:直接返回图片内容
*/
public function byStrategy(Request $request): Response
{
$strategyId = $request->route('strategy_id');
$format = $request->query('format', 'json'); // json, url, raw
// 验证存储策略是否存在
$strategy = Strategy::find($strategyId);
if (!$strategy) {
return $this->fail('存储策略不存在');
}
/** @var User $user */
$user = Auth::user();
// 从该存储策略中随机获取用户的一张图片
$image = $user->images()
->where('strategy_id', $strategyId)
->inRandomOrder()
->first();
if (!$image) {
return $this->fail('该存储策略下没有找到图片');
}
return $this->formatImageResponse($image, $format);
}
/**
* 根据相册ID随机获取一张图片
* 支持三种返回方式:
* - 默认:返回图片信息JSON
* - ?format=url:返回图片URL链接
* - ?format=raw:直接返回图片内容
*/
public function byAlbum(Request $request): Response
{
$albumId = $request->route('album_id');
$format = $request->query('format', 'json'); // json, url, raw
/** @var User $user */
$user = Auth::user();
// 验证相册是否存在且属于当前用户
$album = $user->albums()->find($albumId);
if (!$album) {
return $this->fail('相册不存在或无权访问');
}
// 从该相册中随机获取一张图片
$image = $user->images()
->where('album_id', $albumId)
->inRandomOrder()
->first();
if (!$image) {
return $this->fail('该相册下没有找到图片');
}
return $this->formatImageResponse($image, $format);
}
/**
* 批量随机获取图片
* 支持参数:
* - count: 获取数量,默认5,最大20
* - strategy_id: 限制存储策略
* - album_id: 限制相册
* - type: 限制文件类型
*/
public function batch(Request $request): Response
{
$count = min((int)$request->query('count', 5), 20); // 最多20张
$strategyId = $request->query('strategy_id');
$albumId = $request->query('album_id');
$type = $request->query('type');
/** @var User $user */
$user = Auth::user();
$query = $user->images();
// 添加筛选条件
if ($strategyId) {
$strategy = Strategy::find($strategyId);
if (!$strategy) {
return $this->fail('存储策略不存在');
}
$query->where('strategy_id', $strategyId);
}
if ($albumId) {
$album = $user->albums()->find($albumId);
if (!$album) {
return $this->fail('相册不存在或无权访问');
}
$query->where('album_id', $albumId);
}
if ($type) {
$query->where('extension', strtolower($type));
}
// 随机获取指定数量的图片
$images = $query->inRandomOrder()->limit($count)->get();
if ($images->isEmpty()) {
return $this->fail('没有找到符合条件的图片');
}
// 格式化返回数据
$images->each(function (Image $image) {
$image->human_date = $image->created_at->diffForHumans();
$image->date = $image->created_at->format('Y-m-d H:i:s');
$image->append(['pathname', 'links'])->setVisible([
'album', 'key', 'name', 'pathname', 'origin_name', 'size', 'mimetype', 'extension', 'md5', 'sha1',
'width', 'height', 'links', 'human_date', 'date',
]);
});
return $this->success('获取成功', [
'count' => $images->count(),
'images' => $images
]);
}
/**
* 格式化图片响应
*/
private function formatImageResponse(Image $image, string $format): Response
{
switch ($format) {
case 'url':
// 返回图片URL
return response($image->url, 200, [
'Content-Type' => 'text/plain',
]);
case 'raw':
// 直接返回图片内容
try {
$contents = $image->filesystem()->read($image->pathname);
return response($contents, 200, [
'Content-Type' => $image->mimetype,
'Content-Length' => strlen($contents),
'Cache-Control' => 'public, max-age=3600',
'Content-Disposition' => 'inline; filename="' . $image->origin_name . '"',
]);
} catch (\Exception $e) {
return $this->fail('读取文件失败');
}
default:
// 返回JSON格式的图片信息
$image->human_date = $image->created_at->diffForHumans();
$image->date = $image->created_at->format('Y-m-d H:i:s');
$image->append(['pathname', 'links'])->setVisible([
'album', 'key', 'name', 'pathname', 'origin_name', 'size', 'mimetype', 'extension', 'md5', 'sha1',
'width', 'height', 'links', 'human_date', 'date',
]);
return $this->success('获取成功', $image);
}
}
}
2. 配置路由
编辑 routes/api.php 新增路由(不要忘记引入新建的控制器):
<?php
use App\Http\Controllers\Api\V1\RandomImageController;//20250801 by Tim
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\V1\ImageController;
use App\Http\Controllers\Api\V1\AlbumController;
use App\Http\Controllers\Api\V1\TokenController;
use App\Http\Controllers\Api\V1\UserController;
use App\Http\Controllers\Api\V1\StrategyController;
use App\Http\Middleware\CheckIsEnableApi;
Route::group([
'prefix' => 'v1',
'middleware' => CheckIsEnableApi::class,
], function () {
Route::get('strategies', [StrategyController::class, 'index']);
Route::post('upload', [ImageController::class, 'upload']);
Route::post('tokens', [TokenController::class, 'store'])->middleware('throttle:3,1');
Route::group([
'middleware' => 'auth:sanctum',
], function () {
Route::get('images', [ImageController::class, 'images']);
Route::delete('images/{key}', [ImageController::class, 'destroy']);
Route::get('albums', [AlbumController::class, 'index']);
Route::delete('albums/{id}', [AlbumController::class, 'destroy']);
Route::delete('tokens', [TokenController::class, 'clear']);
Route::get('profile', [UserController::class, 'index']);
//20250801 by Tim 新增:随机图片相关路由
Route::get('random-image', [RandomImageController::class, 'random']);
Route::get('strategies/{strategy_id}/random-image', [RandomImageController::class, 'byStrategy']);
Route::get('albums/{album_id}/random-image', [RandomImageController::class, 'byAlbum']);
Route::get('random-images/batch', [RandomImageController::class, 'batch']);
});
});
🧪 使用示例
🔀 随机获取图片
# 获取任意图片
curl -H "Authorization: Bearer your_token" \
"https://your-lsky.com/api/v1/random-image"
# 获取 PNG 图片
curl -H "Authorization: Bearer your_token" \
"https://your-lsky.com/api/v1/random-image?type=png"
📤 不同返回格式
# 返回图片URL
curl -H "Authorization: Bearer your_token" \
"https://your-lsky.com/api/v1/random-image?format=url"
# 下载原图文件
curl -H "Authorization: Bearer your_token" \
"https://your-lsky.com/api/v1/random-image?format=raw"
🧩 条件与批量获取
# 批量获取 5 张 JPG
curl -H "Authorization: Bearer your_token" \
"https://your-lsky.com/api/v1/random-images/batch?count=5&type=jpg"
# 从指定策略
curl -H "Authorization: Bearer your_token" \
"https://your-lsky.com/api/v1/strategies/1/random-image"
# 从相册获取
curl -H "Authorization: Bearer your_token" \
"https://your-lsky.com/api/v1/albums/3/random-image?format=url"
✅ 总结
成功为LSky Pro添加了如下 4 个随机图片接口:
| 功能 | 接口地址 |
|---|---|
| 基础随机图 | GET /api/v1/random-image |
| 按策略获取 | GET /api/v1/strategies/{strategy_id}/random-image |
| 按相册获取 | GET /api/v1/albums/{album_id}/random-image |
| 批量获取 | GET /api/v1/random-images/batch |
- 0
- 1
-
分享