You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel文件下载接口报500错误:Route [login]未定义

Laravel文件下载500错误排查与解决

问题场景

使用Laravel开发时,从storage获取文件下载链接触发500错误,请求携带的token验证正常。FilesController的store方法可正常完成文件上传,但show方法无法工作,AuthController所有功能正常。

错误日志

Symfony\Component\Routing\Exception\RouteNotFoundException: Route [login] not defined。

相关代码文件

api.php

<?php

use App\Http\Controllers\AuthController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\FilesController;


Route::fallback(function () {
return abort(404);
// return view('errors.404');  // incase you want to return view
});     

Route::middleware(['auth:sanctum', 'ability:admin'])->get('/user', function (Request $request) {
if($request->user()->role == "user") return abort(403);
return response($request->user(), 200);
});

Route::get('/auth/test', [AuthController::class, 'test'])->middleware(['auth:sanctum', 'ability:admin']);

Route::post('/auth/register', [AuthController::class, 'register']);
Route::post('/auth/login', [AuthController::class, 'login']);
Route::post('/auth/logout', [AuthController::class, 'logout'])->middleware('auth:sanctum');

Route::group(['middleware' => ['auth:sanctum','ability:admin']], function() {
Route::resource('files', FilesController::class);
});

AuthController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth;

class AuthController extends Controller
{
public function register(Request $request)
{
    $data = $request->validate([
        'name' => 'required|string',
        'email' => 'required|string|unique:users,email',
        'password' => 'required|string|'
    ]);

    $user = User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => bcrypt($data['password']),
        'role' => 'admin'
    ]);

    $token = $user->createToken('token', [$user->role])->plainTextToken;

    $res = [
        'user' => $user,
        'token' => $token
    ];
    return response($res, 201);
}

public function login(Request $request)
{
    $data = $request->validate([
        'email' => 'required|string',
        'password' => 'required|string'
    ]);

    $user = User::where('email', $data['email'])->first();

    if (!$user || !Hash::check($data['password'], $user->password)) {
        return response([
            'message' => 'incorrect username or password'
        ], 401);
    }

    $token = $user->createToken('token', [$user->role])->plainTextToken;

    $res = [
        'user' => $user,
        'token' => $token
    ];

    return response($res, 201);
}

public function logout(Request $request)
{
    $request->user()->tokens()->delete();
    $response = ['message' => 'You have been successfully logged out!'];
    return response($response, 200);
}

public function test(Request $request)
{
    if($request->user()->role == "user") return response(['message' => 'user'], 200);
    if($request->user()->role == "admin") return response(['message' => 'admin'], 200);
}}

FilesController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\File\File;

class FilesController extends Controller
{
public function index()
{
    //
}

/**
 * Show the form for creating a new resource.
 */
public function create()
{
    //
}

/**
 * Store a newly created resource in storage.
 */
public function store(Request $request)
{

    $data = $request->validate([
        'file' => 'required|mimes:pdf|max:2048'
    ]);


    if ($file = $request->file('file')) {
        $path = $file->store('public/files');
        $name = $file->getClientOriginalName();
        $name2 = $file->hashName();

        // //store your file into directory and db
        // $save = new File();
        // $save->name = $file;
        // $save->store_path = $path;
        // $save->save();

        return response()->json([
            "success" => true,
            "message" => "File successfully uploaded",
            "file" => $file,
            "name" => $name, //oryginalna nazwa pliku
            "path" => $path, // path do pliku np. "public/files/wy8NNSV9uAvL0NPYydw5iaZDkz5XQYeFo2A7VZo0.pdf"
            "name2" => $name2 // sama nazwa pliku np. "wy8NNSV9uAvL0NPYydw5iaZDkz5XQYeFo2A7VZo0.pdf"
        ]);
    }
}

/**
 * Display the specified resource.
 */
public function show(string $filename)
{
    // tutaj powinno być id pliku i z bazy nazwa ale jako id tutaj przekazana jest nazwa pliku z storage

    $file = new File(Storage::disk('public_files')->get($filename));
    return response()->download($file->getRealPath(), $filename);
}

/**
 * Show the form for editing the specified resource.
 */
public function edit(string $id)
{
    //
}

/**
 * Update the specified resource in storage.
 */
public function update(Request $request, string $id)
{
    //
}

/**
 * Remove the specified resource from storage.
 */
public function destroy(string $id)
{
    //
}}

config/filesystems.php

'public_files' => [
        'driver' => 'local',
        'root' => storage_path('app/public/files'),
        'url' => env('APP_URL').'/storage/files',
        'visibility' => 'public',
    ],

文件结构

文件结构截图

问题分析与解决方案

核心原因

  1. 错误提示Route [login] not defined,是因为response()->download()触发了Laravel的ShareErrorsFromSession中间件,该中间件默认尝试跳转至web端的login命名路由,但API路由中未定义此路由。
  2. FilesController的show方法存在文件操作错误:Storage::disk('public_files')->get($filename)返回的是文件内容而非路径,直接传入File类构造器会导致实例化失败。

修复步骤

  1. 修正FilesController的show方法:
    替换原show方法代码,使用正确的文件路径获取方式,同时避免触发web认证跳转逻辑:

    public function show(string $filename)
    {
        $disk = Storage::disk('public_files');
        
        if (!$disk->exists($filename)) {
            return response()->json(['message' => '文件不存在'], 404);
        }
        
        $filePath = $disk->path($filename);
        return response()->download($filePath, $filename)->withHeaders([
            'Cache-Control' => 'no-cache, no-store, must-revalidate',
            'Pragma' => 'no-cache',
            'Expires' => '0',
        ]);
    }
    
  2. 验证API路由匹配:
    确认files资源路由的show方法对应URL为/api/files/{file},请求时需传入上传接口返回的name2字段值作为文件名参数。

  3. 确认API中间件配置:
    确保routes/api.php未加载web端的会话、认证中间件(Laravel默认已通过RouteServiceProvider排除,若有自定义配置需检查)。

内容的提问来源于stack exchange,提问作者MISIU

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 08:29:51