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

Laravel 9调用Storage::url()无法获取S3文件,报403错误

Laravel 9 上传AWS S3文件后访问URL返回403 Forbidden问题

Laravel 9项目中,文件可正常上传至AWS S3存储并将路径保存至数据库,但调用Storage::url()生成的文件URL访问时返回403(Forbidden)错误,已确认.env文件中AWS相关配置齐全,无法定位问题原因。

文件上传代码

public function uploadDoc(Request $request)
{
    $request->validate([
        'arquivo' => 'required|file|mimes:pdf,jpg,jpeg,png,doc,docx,txt,gif|max:25000',
    ], [
        'arquivo.required' => 'Por favor, selecione um arquivo.',
        'arquivo.file' => 'O arquivo deve ser um arquivo válido.',
        'arquivo.max' => 'O tamanho máximo do arquivo é de 25MB.',
        'arquivo.mimes' => 'Apenas os formatos de arquivo PDF, JPG, JPEG, PNG, DOC, DOCX, TXT e GIF são aceitos.',
    ]);

    $vendor = Vendor::findOrFail($request->vendor);

    $file = $request->file('arquivo');
    $filePath = $file->storeAs('vendors/'.$vendor->cnpj.'/documentos', $file->getClientOriginalName(), 's3');

    if (! $filePath) {
        return $this->sendError('Ocorreu um erro ao fazer o upload do arquivo.', 'Ocorreu um erro ao fazer o upload do arquivo.');
    }

    try {
        $document = new Document([
            'vendor_id' => $vendor->id,
            'id_status_vendor_document' => StatusDocumentVendor::DOCUMENTO_ENVIADO,
            'file' => $filePath,
        ]);

        $document->save();

        return $this->sendResponse($filePath, 'Arquivo enviado com sucesso.');

    } catch (\Exception $e) {
        return $this->sendError('Ocorreu um erro ao fazer o upload do arquivo.', $e->getMessage());
    }
}

数据库存储的文件路径示例

{
    "id_document_notebook": null,
    "vendor_id": 10,
    "send_date": null,
    "approved_date": null,
    "due_date": null,
    "id_status_vendor_document": 1,
    "created_at": "2023-09-27 15:53:29",
    "updated_at": "2023-09-27 15:53:29",
    "created_by": null,
    "modified_by": null,
    "file": "vendors/43354933000190/documentos/logo-curvado.png",
    "id": 8
}

文件获取代码

public function teste()
{
    $files = Document::all();
    foreach ($files as $file) {
        $file->file = Storage::url($file->file);
    }

    return view('welcome', compact('files'));
}

视图代码

@foreach($files as $file)
    <img src="{{ $file->file }}" alt="Image">
@endforeach

生成的HTML及错误信息

生成的HTML

<img src="https://s3.amazonaws.com/sgfor-imagens-dev/vendors/43354933000190/documentos/logo-curvado.png" alt="Image">
<img src="https://s3.amazonaws.com/sgfor-imagens-dev/vendors/43354933000190/documentos/Meu%20projeto.png" alt="Image">

浏览器控制台错误

all-documents:2     GET https://s3.amazonaws.com/sgfor-imagens-dev/vendors/43354933000190/documentos/Meu%20projeto.png 403 (Forbidden)
all-documents:1     GET https://s3.amazonaws.com/sgfor-imagens-dev/vendors/43354933000190/documentos/logo-curvado.png 403 (Forbidden)

排查与解决方案

  1. 设置文件上传时的可见性
    默认上传到S3的文件权限为私有,需显式设置为公共可读,修改上传代码:

    $filePath = $file->storeAs(
        'vendors/'.$vendor->cnpj.'/documentos',
        $file->getClientOriginalName(),
        [
            'disk' => 's3',
            'visibility' => 'public'
        ]
    );
    
  2. 使用预签名URL(适用于私有文件)
    如果不需要公开文件,改用临时预签名URL,替换文件获取代码中的Storage::url():

    $file->file = Storage::disk('s3')->temporaryUrl(
        $file->file,
        now()->addMinutes(60) // 自定义有效期
    );
    
  3. 检查S3存储桶策略
    若要公开访问文件,需给存储桶添加允许公共读取的策略(注意敏感文件公开的安全风险):

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": "*",
                "Action": "s3:GetObject",
                "Resource": "arn:aws:s3:::sgfor-imagens-dev/*"
            }
        ]
    }
    
  4. 验证IAM用户权限
    确认.env中配置的IAM用户拥有s3:GetObject权限,避免因权限不足导致403。

  5. 核对存储桶区域配置
    确保.env中的AWS_DEFAULT_REGION与S3存储桶实际所在区域完全一致,区域不匹配也会引发访问错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 03:10:02