master
lion 2 days ago
parent 277492a1e5
commit a6d1dc3039

@ -6,6 +6,8 @@ use App\Http\Controllers\Controller;
use App\Models\WechatUser;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Throwable;
class H5UploadController extends Controller
{
@ -16,15 +18,35 @@ class H5UploadController extends Controller
abort(403, '仅微信用户可上传');
}
if (!$request->hasFile('file')) {
return response()->json(['message' => '未收到文件'], 422);
}
$uploaded = $request->file('file');
if (!$uploaded->isValid()) {
return response()->json(['message' => $uploaded->getErrorMessage()], 422);
}
$data = $request->validate([
'file' => ['required', 'file', 'max:5120', 'mimes:jpg,jpeg,png,gif,webp'],
]);
$path = $data['file']->store('uploads/h5', 'public');
$url = url('/storage/'.$path);
try {
$path = Storage::disk('public')->putFile('uploads/h5', $data['file']);
} catch (Throwable $e) {
report($e);
return response()->json(['message' => '文件保存失败'], 500);
}
if ($path === false) {
return response()->json(['message' => '文件保存失败'], 500);
}
$safePath = str_replace('\\', '/', $path);
return response()->json([
'url' => $url,
'url' => url('/storage/'.$safePath),
'path' => $path,
]);
}

@ -5,21 +5,75 @@ namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Throwable;
class UploadController extends Controller
{
public function store(Request $request): JsonResponse
{
if (!$request->hasFile('file')) {
return response()->json([
'message' => '未收到文件,请使用 multipart 表单字段名 file。',
], 422);
}
$uploaded = $request->file('file');
if (!$uploaded->isValid()) {
return response()->json([
'message' => '上传未通过校验:'.$uploaded->getErrorMessage(),
], 422);
}
$data = $request->validate([
'file' => ['required', 'file', 'max:20480'],
]);
$path = $data['file']->store('uploads', 'public');
try {
$path = Storage::disk('public')->putFile('uploads', $data['file']);
} catch (Throwable $e) {
report($e);
return response()->json([
'message' => '文件保存失败',
], 500);
}
if ($path === false) {
return response()->json([
'message' => '文件保存失败',
], 500);
}
try {
$mime = $data['file']->getMimeType()
?: $data['file']->getClientMimeType()
?: 'application/octet-stream';
} catch (Throwable) {
$mime = 'application/octet-stream';
}
return response()->json([
'path' => $path,
'url' => url('/storage/' . $path),
'mime' => $data['file']->getClientMimeType(),
'url' => url('/storage/'.str_replace('\\', '/', $path)),
'mime' => self::jsonSafeString($mime),
'size' => $data['file']->getSize(),
]);
}
/** 避免 mime 等字段含非法 UTF-8 导致 json_encode 抛错成 500 */
private static function jsonSafeString(string $value): string
{
if ($value === '') {
return '';
}
if (function_exists('mb_scrub')) {
return mb_scrub($value, 'UTF-8');
}
$clean = @iconv('UTF-8', 'UTF-8//IGNORE', $value);
return $clean !== false ? $clean : 'application/octet-stream';
}
}

@ -54,8 +54,13 @@ class AuditLogMiddleware
return false;
}
// multipart 上传不参与审计,避免大 payload 与序列化问题
if ($request->is('api/upload') || $request->is('api/h5/upload')) {
// 任意 multipart 文件请求不参与审计(避免路径前缀不一致时仍序列化 UploadedFile
if ($request->files->count() > 0) {
return false;
}
// 仍按路由名兜底(无文件字段但走上传 URL 的极端情况)
if ($request->is('api/upload') || $request->is('api/h5/upload') || $request->is('*/api/upload') || $request->is('*/api/h5/upload')) {
return false;
}

Loading…
Cancel
Save