无法将附加文件传递给控制器​​:422 无法处理的实体

Unable to pass attached files to controller: 422 Unprocessable Entity

我正在使用 Dropzone js 处理多个文件上传。但是,文件不会传递给控制器​​。通过为 CSRF 令牌添加 header 代码解决 419 post 错误后,出现 422 无法处理的实体错误。

根据网络日志的响应,它似乎影响了我之前工作正常的其他字段的验证。

{"message":"The given data was invalid.","errors":{"item-name.0":["The item-
name.0 field is required."],"item-quantity.0":["Please Enter Item 
Quantity."],"availableStartDate":["The available start date field is 
required."],"availableEndDate":["The available end date field is 
required."],"preferredTime":["The preferred time field is required."]}}

这是 Blade 文件顶部的 Javascript 代码。

 <script type="text/javascript">
    Dropzone.autoDiscover = false;
    $(document).ready(function () {
        new Dropzone('#fileInput', {
            autoProcessQueue: false,
            uploadMultiple: true,
            parallelUploads: 1000,
            maxFiles: 100,
            acceptedFiles: ".jpeg,.jpg,.png,.gif",
            url: '/make-a-donation',
            addRemoveLinks:true,
            headers: {
                'X-CSRFToken': $('meta[name="token"]').attr('content')
            },

            init: function () {

                var myDropzone = this;
                var wrapperThis = this;
                $("#submit-all").click(function (e) {
                    e.preventDefault();
                    myDropzone.processQueue();
                });

                //Removed sending and success functions respectively

            }
        });
    });
</script>

这里是 HTML 代码:

<form class="form-horizontal myForm" method="POST" files="true" action="{{ 
route('postdonation') }}"  enctype="multipart/form-data">
{{ csrf_field() }}

 <div class="col-md-12">

             <div id="fileInput" class="dropzone">
             <div class="fallback">
             <!--replaced files[] to file-->
             <input name="file" type="file" multiple="multiple" id="fileUpload"/>
             </div>
             </div>
</div>

....

<div class="form-group">
     <div class="col-md-6 col-md-offset-4">
           <button type="submit" id="submit-all" class="btn btn-primary">
               insert
            </button>
      </div>
 </div>
 ...
 </form>

在控制器上,

   public function store(CreateDonationDetailsRequest $r) {

   //Inserting other data in the form
   .....

  //Previously $r->file('files') as $file to
    foreach ($r->file('file') as $file) {
        $donationImages = new DonationImages();

        // Set the destination path
        $destination = '/donationImagesUpload/';
        // Get the orginal filname or create the filename of your choice
        $filename = $file->getClientOriginalName();

        // Copy the file to the destination folder
        $file->move(public_path($destination), $filename);

        //Insert file name to database
        $donationImages->donation_items_id = $donationItems->id;
        $donationImages->photoName = $filename;

        //Save images to database
        $donationItems->donationImages()->save($donationImages);

    }

    ..
}

问题 1

您的提交处理程序选择器是 #submit-all:

$("#submit-all").click(function (e) {

但您的按钮没有该 ID(其他任何东西也没有):

<button type="submit" class="btn btn-primary">

所以您的提交处理程序永远不会被触发,这意味着 processQueue() 永远不会被调用,所以实际上没有文件被 POSTed。

问题2

您尝试将文件附加到 formData 的下一个问题,但它们已经存在 - 这就是 processQueue() 所做的。您可以完全删除 sending 事件处理程序。

问题3

接下来,from the Dropzone docs

The uploaded files can be handled just as if there would have been a html input like this: <input type="file" name="file" />

所以在你的控制器中,你应该寻找一个名为 file 的输入,而不是 files:

foreach ($r->file('file') as $file) {

问题4

接下来,在您的 success 回调中,您正尝试以 e 的身份访问 Javascript 事件和上传的 file 但它们都没有在此处定义,所以会抛出错误。 According to the docs,POST 响应作为第二个参数可用,但我不确定第一个是什么(控制台日志显示它是某种 Dropzone 对象)。

请注意,文档还说:

Do not overwrite those as configuration options, unless you know what you're doing.

我会完全删除 success 回调。如果上传成功后要删除文件,the docs show exactly how to do that:

myDropzone.on("complete", function(file) {
  myDropzone.removeFile(file);
});

解决了这些问题中的每一个,我让您的代码在我的本地环境中正常工作。

另一件事,我不确定它是否只是这里的错字,或者你的代码中是否真的有这个,但是你在 [=28] 之间的后备文件输入中缺少 space =] 及其 id,这可能会在需要时将其搞乱:

multiple="multiple"id="fileUpload"

更新以回答新问题 5

对于您的新问题,419 通常是因为您的 CSRF 令牌检查失败。 SO 上有几个带有解决方案的示例:example 1, example 2

对于我自己的一个项目,我使用 Dropzone sending 回调将其他表单输入包含在 POSTed 数据中:

this.on('sending', function(file, xhr, formData) {
    // Append all form inputs to the formData Dropzone will POST
    var data = $('form').serializeArray();
    $.each(data, function(key, el) {
        formData.append(el.name, el.value);
    });
});

更新以回答新问题 6

对于你的新问题:

Now it leads to another error: 422 unprocessable entity

Laravel returns 422 对于未通过验证的 AJAX 请求。

听起来您 a) 表单中的字段比您显示的多,并且 b) 对它们进行了验证。目前,您只是 POST 正在处理文件,没有别的,所以您的验证自然会失败。

在这种情况下,您需要在 POST 中包含其他字段。您可以通过将它们附加到 formData 来实现,如上次更新中包含的 sending 回调所示。