无法将附加文件传递给控制器​​:422 Unprocessable Entity

时间:2017-10-08 07:47:49

标签: javascript php laravel laravel-5 dropzone

我正在使用Dropzone js来处理多个文件上传。但是,文件不会传递给控制器​​。通过添加CSRF令牌的标头代码解决419错误后,出现了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 个答案:

答案 0 :(得分:1)

问题1

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

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

但是你的按钮没有那个ID(也没有其他任何东西):

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

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

问题2

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

问题3

接下来,from the Dropzone docs

  

上传的文件可以像处理这样的html输入一样处理:<input type="file" name="file" />

因此,在您的控制器中,您应该查找名为file的输入,而不是files

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

问题4

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

请注意,文档也说:

  

除非您知道自己在做什么,否则不要将这些选项覆盖为配置选项。

我会彻底删除success回调。如果要在成功上传后删除文件,请the docs show exactly how to do that

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

修复了上述每个问题,我的代码在我的本地环境中正常运行。

另一件事,我不确定它是否只是在SO上的错字,或者你的代码中是否真的有这个错误,但你在multiple和它的{id之间的后备文件输入中缺少一个空格1}},在需要时可能会搞乱它:

multiple="multiple"id="fileUpload"

更新以回答新问题5

对于您的新问题,419通常是bcs您的CSRF令牌检查失败。在SO上有几个解决方案示例:example 1example 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

对于您的新问题:

  

现在它导致另一个错误:422无法处理的实体

Laravel returns 422表示未通过验证的AJAX请求。

所以听起来你有a)表格中的字段多于你所显示的字段,b)对它们进行验证。目前,您只是在发布文件,没有其他内容,因此您的验证自然会失败。

在这种情况下,您需要在POST中包含其他字段。您可以将其添加到formData,如上所示我之前更新中包含的sending回调中所示。