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)
排查与解决方案
设置文件上传时的可见性
默认上传到S3的文件权限为私有,需显式设置为公共可读,修改上传代码:$filePath = $file->storeAs( 'vendors/'.$vendor->cnpj.'/documentos', $file->getClientOriginalName(), [ 'disk' => 's3', 'visibility' => 'public' ] );使用预签名URL(适用于私有文件)
如果不需要公开文件,改用临时预签名URL,替换文件获取代码中的Storage::url():$file->file = Storage::disk('s3')->temporaryUrl( $file->file, now()->addMinutes(60) // 自定义有效期 );检查S3存储桶策略
若要公开访问文件,需给存储桶添加允许公共读取的策略(注意敏感文件公开的安全风险):{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::sgfor-imagens-dev/*" } ] }验证IAM用户权限
确认.env中配置的IAM用户拥有s3:GetObject权限,避免因权限不足导致403。核对存储桶区域配置
确保.env中的AWS_DEFAULT_REGION与S3存储桶实际所在区域完全一致,区域不匹配也会引发访问错误。
内容的提问来源于stack exchange,提问作者Marcello Pato
相关产品推荐
相关产品推荐

