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

Laravel项目中Summernote附件存AWS S3遇CORS问题求解

解决Laravel+Summernote上传附件到AWS S3的CORS问题

1. 配置AWS S3的CORS规则

CORS错误的核心原因是S3存储桶未允许你的Laravel域名发起跨域请求,直接在AWS控制台修改存储桶的CORS配置:

  1. 登录AWS控制台,进入目标S3存储桶的「权限」标签
  2. 找到「跨域资源共享(CORS)」,替换为以下规则(根据实际环境修改域名):
[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "PUT",
            "POST",
            "DELETE"
        ],
        "AllowedOrigins": [
            "http://localhost:8000", // 本地开发域名
            "https://your-production-domain.com" // 生产环境域名
        ],
        "ExposeHeaders": [
            "ETag"
        ]
    }
]

注意:生产环境尽量指定具体域名,避免使用*;AWS配置生效可能需要1-2分钟,修改后稍等再测试。

2. Laravel端签名与上传逻辑

2.1 配置S3连接

确保.env文件中AWS配置正确:

AWS_ACCESS_KEY_ID=你的AWS访问密钥ID
AWS_SECRET_ACCESS_KEY=你的AWS秘密访问密钥
AWS_DEFAULT_REGION=你的存储桶区域(如us-east-1)
AWS_BUCKET=你的存储桶名称
AWS_URL=https://你的存储桶访问域名(可选,如CloudFront域名)
AWS_USE_PATH_STYLE_ENDPOINT=false

2.2 编写签名路由与控制器

在routes/web.php添加签名接口路由:

Route::post('/summernote/sign-s3', [SummernoteController::class, 'signS3'])->name('summernote.sign-s3');

创建SummernoteController并实现签名逻辑:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class SummernoteController extends Controller
{
    public function signS3(Request $request)
    {
        $file = $request->file('file');
        $s3 = Storage::disk('s3');
        $client = $s3->getDriver()->getAdapter()->getClient();
        
        // 生成唯一文件路径,避免重名
        $fileKey = 'summernote-uploads/' . uniqid() . '-' . $file->getClientOriginalName();
        
        // 创建S3预签名上传请求
        $command = $client->getCommand('PutObject', [
            'Bucket' => config('filesystems.disks.s3.bucket'),
            'Key' => $fileKey,
            'ContentType' => $file->getMimeType(),
            'ACL' => 'public-read', // 根据需求设置,如private需配合签名访问
        ]);
        
        $presignedRequest = $client->createPresignedRequest($command, '+15 minutes');
        
        return response()->json([
            'presigned_url' => (string)$presignedRequest->getUri(),
            'public_url' => $s3->url($fileKey)
        ]);
    }
}

确保IAM用户拥有S3的PutObject权限,可给用户附加AmazonS3FullAccess或更精细的权限策略。

3. Summernote前端配置

修改Summernote初始化代码,替换默认上传逻辑为S3上传:

$(document).ready(function() {
    $('#summernote').summernote({
        height: 350,
        callbacks: {
            // 处理图片上传
            onImageUpload: function(files) {
                uploadToS3(files[0], 'image');
            },
            // 处理视频上传
            onMediaUpload: function(files) {
                uploadToS3(files[0], 'video');
            }
        }
    });

    function uploadToS3(file, type) {
        const formData = new FormData();
        formData.append('file', file);

        // 第一步:获取S3预签名URL
        $.ajax({
            url: '{{ route('summernote.sign-s3') }}',
            method: 'POST',
            headers: {
                'X-CSRF-TOKEN': '{{ csrf_token() }}'
            },
            data: formData,
            processData: false,
            contentType: false,
            success: function(res) {
                // 第二步:通过预签名URL上传文件到S3
                $.ajax({
                    url: res.presigned_url,
                    method: 'PUT',
                    data: file,
                    contentType: file.type,
                    processData: false,
                    success: function() {
                        // 上传成功后插入到编辑器
                        if (type === 'image') {
                            $('#summernote').summernote('insertImage', res.public_url);
                        } else {
                            $('#summernote').summernote('insertVideo', res.public_url);
                        }
                    },
                    error: function(xhr) {
                        console.error('S3上传失败:', xhr.responseText);
                    }
                });
            },
            error: function(xhr) {
                console.error('获取签名失败:', xhr.responseText);
            }
        });
    }
});

4. 常见问题排查

  • 仍报CORS错误:检查S3的AllowedOrigins是否与请求域名完全匹配(包括HTTP/HTTPS、端口号),等待AWS配置同步完成。
  • 预签名上传失败:检查签名中的ContentType是否与文件实际MIME类型一致,以及IAM用户的S3权限是否足够。
  • Laravel报419错误:确保前端请求带上了CSRF令牌,或者将签名路由加入VerifyCsrfToken白名单(不推荐)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 19:01:25