Laravel图片上传POST请求返回405错误,路由与方法已存在
Laravel拖拽上传图片返回405 Method Not Allowed问题排查与解决
我是Laravel开发新手,正在构建支持表单和拖拽上传图片的小型应用。尝试通过POST路由及Controller的store方法上传图片时,应用始终返回ERROR 405 - Method Not Allowed,相关代码如下:
相关代码
web.php路由配置
Route::resource('colaboradores', ColaboradoresController::class, ['only' => ['index', 'store', 'update', 'destroy']]);
拖拽区域表单代码
<form enctype="multipart/form-data" action="{{ route('administrativo.secoes.colaboradores.store') }}" id="image-upload-form"> <input type="file" name="file" id="image-input" class="dropzone-input" onchange="get_images(this)" multiple hidden> <div class="drop-zone" id="image-dropzone" ondragover="dragOverHandler(event);" ondrop="dropHandler(event);"> <div class="inner-elements"> <label for="image-input"> <h3>Drag your pictures here</h3> <span class="note needsclick">Or click here to manually select them.</span> </label> </div> </div> </form>
AJAX请求的JavaScript代码
function dragOverHandler(ev) { document.getElementById("image-dropzone").style.border = "3px solid #00f752"; ev.preventDefault(); } function dropHandler(ev) { document.getElementById("image-dropzone").style.border = "3px dashed #0087f7"; ev.preventDefault(); if (ev.dataTransfer.items) { [...ev.dataTransfer.items].forEach((item, i) => { if (item.type.includes("image")) { const file = item.getAsFile(); upload_image(file); } }); } } function get_images() { var total_images = document.getElementById("image-input").files.length; if (total_images > 0) { for (var index = 0; index < total_imagens; index++) { var file = document.getElementById("image-input").files[index]; upload_image(file); } } } function upload_image(file) { var form_data = new FormData(); form_data.append("file", file); form_data.append("test", "test"); $.ajaxSetup({ headers: { "X-CSRF-TOKEN": $("meta[name='csrf-token']").attr("content") } }); $.ajax({ type: "PUT", url: `${window.location.pathname}/store/`, data: form_data, cache: false, contentType: false, processData: false, success: function (data) { console.log(data); }, error: function (data) { console.log(data); } }); }
ColaboradoresController.php代码
<?php namespace App\Http\Controllers\Administrativo; use App\Http\Controllers\Controller; use App\Models\SectionCollaborators; use Exception; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Validator; class ColaboradoresController extends Controller { public function index() { // } public function create() { // } public function store(Request $request) { try { $novo_nome = self::upload_imagem($request); return response()->json(["imagem" => "$novo_nome", "mensagem" => "Imagem salva com sucesso."], 200); } catch (Exception $e) { return response()->json(["mensagem" => "Ocorreu um erro ao salvar a imagem. Tente novamente."], 500); } } private function upload_imagem(Request $request) { if ($request->hasFile('file') && $request->file('file')->isValid()) { $request->validate([ 'file' => 'required|image|mimes:jpeg,png,jpg,webm,svg|max:2048', ]); $img = $request->file; $novo_nome = Storage::disk('local')->put('public/img/colaboradores/cards', $img, 'public'); return basename($novo_nome); } } public function update(Request $request) { // } private function update_text($object, $nome, $valor) { // } public function destroy(Request $request) { // } public function setId(int $value) { // } public function getId() { // } }
核心错误原因及修复方案
1. 请求方法不匹配
Laravel资源路由的store方法默认只接受POST请求,但你的AJAX代码里用了PUT方法,这直接导致405错误。
修复:将AJAX的请求类型改为POST:
$.ajax({ type: "POST", // 替换原有的"PUT" // ...其他参数 });
2. 请求URL错误
你手动拼接的URL ${window.location.pathname}/store/ 大概率和路由定义的实际地址不匹配,而表单里已经通过route('administrativo.secoes.colaboradores.store')生成了正确的URL,应该复用这个地址。
修复:
- 先给表单添加一个存储路由URL的属性:
<form enctype="multipart/form-data" action="{{ route('administrativo.secoes.colaboradores.store') }}" id="image-upload-form" data-store-url="{{ route('administrativo.secoes.colaboradores.store') }}">
- 然后在JS中获取这个正确的URL:
function upload_image(file) { // 获取表单中存储的正确路由URL const storeUrl = document.getElementById('image-upload-form').dataset.storeUrl; var form_data = new FormData(); form_data.append("file", file); form_data.append("test", "test"); $.ajaxSetup({ headers: { "X-CSRF-TOKEN": $("meta[name='csrf-token']").attr("content") } }); $.ajax({ type: "POST", url: storeUrl, // 使用正确的路由URL data: form_data, cache: false, contentType: false, processData: false, success: function (data) { console.log(data); }, error: function (data) { console.log(data); } }); }
3. JavaScript变量拼写错误
get_images函数中,循环条件里的total_imagens是拼写错误,应该是total_images,否则手动选择图片时循环不会执行。
修复:
function get_images() { var total_images = document.getElementById("image-input").files.length; if (total_images > 0) { // 把total_imagens改为total_images for (var index = 0; index < total_images; index++) { var file = document.getElementById("image-input").files[index]; upload_image(file); } } }
4. 验证路由命名是否正确
确保你的路由分组配置正确,生成的路由名称和route('administrativo.secoes.colaboradores.store')一致。如果路由是嵌套在分组里,需要这样配置:
Route::prefix('administrativo/secoes')->name('administrativo.secoes.')->group(function () { Route::resource('colaboradores', ColaboradoresController::class, ['only' => ['index', 'store', 'update', 'destroy']]); });
可以通过执行php artisan route:list命令查看所有路由的详细信息,确认store路由的请求方法是POST,名称和URL正确。
额外建议
- 上传文件时,确保
upload_imagem方法中处理了文件验证失败的情况,比如添加返回值或抛出异常,避免出现静默错误。 - 测试时可以在浏览器控制台查看AJAX请求的具体URL和方法,确认和路由定义一致。
内容的提问来源于stack exchange,提问作者Gian Luca Oliveira
相关产品推荐
相关产品推荐

