master
lion 3 days ago
parent a6d1dc3039
commit 995de3fa42

@ -2,15 +2,19 @@
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Concerns\EnsuresPublicDiskWritable;
use App\Http\Controllers\Controller;
use App\Models\WechatUser;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Throwable;
class H5UploadController extends Controller
{
use EnsuresPublicDiskWritable;
public function store(Request $request): JsonResponse
{
$user = $request->user();
@ -18,6 +22,10 @@ class H5UploadController extends Controller
abort(403, '仅微信用户可上传');
}
if ($early = $this->ensurePublicDiskReady()) {
return $early;
}
if (!$request->hasFile('file')) {
return response()->json(['message' => '未收到文件'], 422);
}
@ -32,15 +40,30 @@ class H5UploadController extends Controller
]);
try {
Storage::disk('public')->makeDirectory('uploads/h5');
$path = Storage::disk('public')->putFile('uploads/h5', $data['file']);
} catch (Throwable $e) {
report($e);
Log::error('h5_upload_putfile_failed', [
'message' => $e->getMessage(),
'public_path' => storage_path('app/public'),
]);
return response()->json(['message' => '文件保存失败'], 500);
return response()->json([
'message' => '文件保存失败',
'detail' => config('app.debug') ? $e->getMessage() : null,
], 500);
}
if ($path === false) {
return response()->json(['message' => '文件保存失败'], 500);
Log::error('h5_upload_putfile_returned_false', [
'public_path' => storage_path('app/public'),
]);
return response()->json([
'message' => '文件保存失败(写入返回失败)',
'detail' => config('app.debug') ? 'Storage::putFile 返回 false' : null,
], 500);
}
$safePath = str_replace('\\', '/', $path);

@ -2,16 +2,24 @@
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Concerns\EnsuresPublicDiskWritable;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Throwable;
class UploadController extends Controller
{
use EnsuresPublicDiskWritable;
public function store(Request $request): JsonResponse
{
if ($early = $this->ensurePublicDiskReady()) {
return $early;
}
if (!$request->hasFile('file')) {
return response()->json([
'message' => '未收到文件,请使用 multipart 表单字段名 file。',
@ -30,18 +38,29 @@ class UploadController extends Controller
]);
try {
Storage::disk('public')->makeDirectory('uploads');
$path = Storage::disk('public')->putFile('uploads', $data['file']);
} catch (Throwable $e) {
report($e);
Log::error('upload_putfile_failed', [
'message' => $e->getMessage(),
'public_path' => storage_path('app/public'),
]);
return response()->json([
'message' => '文件保存失败',
'detail' => config('app.debug') ? $e->getMessage() : null,
], 500);
}
if ($path === false) {
Log::error('upload_putfile_returned_false', [
'public_path' => storage_path('app/public'),
]);
return response()->json([
'message' => '文件保存失败',
'message' => '文件保存失败(写入返回失败)',
'detail' => config('app.debug') ? 'Storage::putFile 返回 false多为磁盘 public 配置或权限问题' : null,
], 500);
}

@ -0,0 +1,41 @@
<?php
namespace App\Http\Controllers\Concerns;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Throwable;
trait EnsuresPublicDiskWritable
{
/**
* 线上常见storage/app/public 对 PHP-FPM 用户不可写,本地开发用户有权限故正常。
*/
protected function ensurePublicDiskReady(): ?JsonResponse
{
$dir = storage_path('app/public');
try {
if (!is_dir($dir)) {
mkdir($dir, 0775, true);
}
} catch (Throwable $e) {
report($e);
return response()->json([
'message' => '无法创建存储目录 storage/app/public',
'detail' => config('app.debug') ? $e->getMessage() : null,
], 500);
}
if (!is_writable($dir)) {
Log::error('upload_public_dir_not_writable', ['path' => $dir]);
return response()->json([
'message' => '存储目录不可写,请在线上为 PHP 运行用户开放 storage 与 bootstrap/cache 写权限',
'hint' => '示例chmod -R ug+rwx storage bootstrap/cache && chown -R www-data:www-data storage bootstrap/cache用户以实际 php-fpm 用户为准)',
], 500);
}
return null;
}
}
Loading…
Cancel
Save