我无法使用 Laravel 通过 ajax PUT 请求发送文件

时间:2021-03-08 12:05:24

标签: ajax laravel file controller request

我有一个输入文件类型为隐藏的表单。图像标签作为可点击的触发器来选择文件本身,用 js 来触发它(有效),但我想在选择图像时自动发出 PUT 请求,而不必单击表单上的提交按钮,每次在输入字段上更改图像时。我为此使用了 ajax,但在处理请求的控制器端点上,我似乎没有任何文件。不过,如果我将其他字段(例如文本)放入控制器中,它们似乎可以通过请求传入控制器就好了。

我的路线:

Route::put('/coins/image/{key}', [CoinController::class, 'image'])->name("coins.image");

我的控制器(还没有实际的图像更新代码;只是我正在检查文件):

public function image(int $key)
{
    dump(request()->file('file'));
    dump(request()->file);
    dump(request());
}

以下代码段中的我的 HTML 和 JS:

function promptImageForUpload(elemId)
{
    $('#' + elemId).click();
}

function uploadImage(event, imgId, key)
{
    event.preventDefault();
    var inputElem = event.target;
    var imageFile = inputElem.files[0];
    var imgElem = $('#' + imgId);
    var form = $(inputElem).parent();
    var formData = new FormData(form[0]);
    formData.append('file', imageFile);
    $.ajax({
        url: "/coins/image/" + key,
        type: "PUT",
        headers: {
            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        },
        data: formData,
        enctype: 'multipart/form-data',
        processData: false,
        contentType: false,
        success: function(response) {
            var reader = new FileReader();
            reader.onload = function(e) {
                imgElem.attr("src", e.target.result);
            };
            reader.readAsDataURL(imageFile); // convert to base64 string
        }
    });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card-body">
   <form data-key="0" id="coin-header-0_form" method="POST" action="#" enctype="multipart/form-data">
      <input type="file" name="file" id="coin-header-0_file" style="z-index:-1; width: 100%; height: 100%; display: none;" onchange="uploadImage(event, 'coin-header-0_preview', 0)">
      <input type="hidden" name="_method" value="PUT">
      <meta name="csrf-token" content="7c3s2NmosdK9qzrS10xGAB0rYXw5g41azRjcmPQC">
      <img src="http://snapbuilder.com/code_snippet_generator/image_placeholder_generator/60x40/007730/DDDDDD/this%20pict" width="50px" height="50px" alt="icon" id="coin-header-0_preview" onclick="promptImageForUpload('coin-header-0_file');">
   </form>
</div>

现在,我在 ajax 成功时强制更新图像的预览,而不是在成功更新时从更新的实体中检索它,以避免第二次查询。

我将方法设置为 PUT 以在 ajax 请求中进行欺骗,并且 xsrf 令牌也设置了标头。 Enctype 也设置为文件的 multipart/form-data。我不知道为什么我在请求中的任何地方都看不到上传的文件。

使用 Laravel 框架 8.25.0,jquery 3.5.1。

如果需要更多信息,请告诉我,任何人。 我无法在任何有关此主题的 stackoverflow 条目或其他地方找到任何解决方案。 非常感谢任何帮助,因为我真的不知道如何在调试方法中查看它。

1 个答案:

答案 0 :(得分:0)

HTML 表单不支持 PUTPATCHDELETE 操作。因此,在定义从 HTML 表单调用的 PUTPATCHDELETE 路由时,您需要向表单添加隐藏的 _method 字段。与 _method 字段一起发送的值将用作 HTTP 请求方法:

<form action="/foo/bar" method="POST">
    <input type="hidden" name="_method" value="PUT">
    <input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>

您可以使用 method_field 助手来生成 _method 输入:

{{ method_field('PUT') }}

同样,这个检查也可能影响ajax表单。然后在您的表单中切换到 POST 方法并设置 PUT 参数使其工作。