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

Laravel 10获取图片时出现CORS错误,请求协助排查

问题描述

使用Laravel 10搭建API,尝试获取public/images文件夹中的图片:

  • 控制器show方法返回图片URL:
public function show()
{
    $imageUrl = asset('images/myimage.png');
    return response()->json(['imageUrl' => $imageUrl]);
}
  • API路由配置:
Route::get('images', [ImageController::class, 'show']);
Route::post('images', [ImageController::class, 'store']);
  • Postman访问http://127.0.0.1:8000/api/images返回正常,直接打开图片URL也能查看,但Angular 15前端请求图片时出现CORS错误:
Access to XMLHttpRequest at 'http://127.0.0.1:8000/images/myimage.png' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
  • 已配置cors.php:
<?php

return [
    'paths' => ['api/*', 'images/*'],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['*'],
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => false,
];
  • 修改了Kernel.php添加CORS中间件,无效果:
protected $middleware = [
    // \App\Http\Middleware\TrustHosts::class,
    \App\Http\Middleware\TrustProxies::class,
    \Illuminate\Http\Middleware\HandleCors::class,
    \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],

    'api' => [
        // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Http\Middleware\HandleCors::class
    ],

    'images' => [
        \Illuminate\Http\Middleware\HandleCors::class
    ]
];
protected $middlewareAliases = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
    'signed' => \App\Http\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
  • Angular配置了代理文件:
{
  "/api/*": {
    "target": "http://localhost:8000",
    "secure": false,
    "logLevel": "debug",
    "changeOrigin": true
  },
  "/images/*": {
    "target": "http://localhost:8000",
    "secure": false,
    "logLevel": "debug"
  }
}
  • Angular请求图片的方法:
getImage(): Observable<Blob> {
  const headers = new HttpHeaders({ 'Content-Type': 'image/png' });
  return this.http.get('http://127.0.0.1:8000/images/myimage.png', { headers, responseType: 'arraybuffer' }).pipe(
    map((response: ArrayBuffer) => {
      return new Blob([response], { type: 'image/png' });
    })
  );
}

解决方案

1. 核心原因

Laravel的HandleCors中间件仅处理通过Laravel路由匹配的请求,而public/images下的静态文件是直接由服务器(如Apache/Nginx)或Laravel底层静态资源处理器返回的,不会触发CORS中间件,因此缺少Access-Control-Allow-Origin响应头。

2. 解决方法一:通过Laravel路由返回图片(推荐)

修改路由配置,将静态图片请求交由控制器处理,手动添加CORS头:

  • 在routes/api.php中添加命名路由:
Route::get('images/{filename}', [ImageController::class, 'serveImage'])->name('images.serve');
  • 在ImageController中新增处理方法:
public function serveImage($filename)
{
    $imagePath = public_path("images/{$filename}");
    
    if (!file_exists($imagePath)) {
        abort(404, 'Image not found');
    }
    
    // 返回图片并添加CORS头
    return response()->file($imagePath)->header('Access-Control-Allow-Origin', '*');
}
  • 修改原show方法返回路由生成的URL:
public function show()
{
    $imageUrl = route('images.serve', ['filename' => 'myimage.png']);
    return response()->json(['imageUrl' => $imageUrl]);
}

3. 解决方法二:正确使用Angular代理

代理配置已正确,但请求未走代理,需修改为相对路径并指定代理启动:

  • 修改Angular的getImage方法:
getImage(): Observable<Blob> {
  const headers = new HttpHeaders({ 'Content-Type': 'image/png' });
  // 使用相对路径,让代理接管请求
  return this.http.get('/images/myimage.png', { headers, responseType: 'arraybuffer' }).pipe(
    map((response: ArrayBuffer) => {
      return new Blob([response], { type: 'image/png' });
    })
  );
}
  • 启动Angular时必须指定代理配置文件:
ng serve --proxy-config proxy.conf.json

4. 额外注意事项

  • 统一源地址:Laravel的asset函数使用127.0.0.1,Angular代理目标是localhost,浏览器会将二者视为不同源,建议统一为同一地址。
  • 无需单独创建images中间件组:全局中间件中已添加HandleCors,足够处理所有路由请求,静态资源问题需通过上述两种方法解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:42:03