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'], ]); 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/'.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'; } }