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

Posted

技术标签:

【中文标题】无法将附件传递给控制器​​:422 Unprocessable Entity【英文标题】:Unable to pass attached files to controller: 422 Unprocessable Entity 【发布时间】:2018-03-19 14:46:43 【问题描述】:

我正在使用 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);

    

    ..

【问题讨论】:

表格enctype? @skido 已经在表单标签处添加了 enctype="multipart/form-data" @Enovyne 我的更新有帮助吗? @Don't Panic 之类的。现在它导致另一个错误:422 unprocessable entity。 现在您只发布文件。如果您在此表单中有其他字段,并且它们是验证所必需的,则需要在您发布的数据中包含这些值。您可以使用我上次更新中包含的 sending 回调来做到这一点。 【参考方案1】:

问题 1

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

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

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

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

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

问题 2

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

问题 3

接下来,from the Dropzone docs:

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

因此,在您的控制器中,您应该寻找一个名为 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 之间的后备文件输入中缺少一个空格,在需要的情况下可能会搞砸:

multiple="multiple"id="fileUpload"

更新以回答新问题 5

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

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

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 unprocessable entity

Laravel returns 422 用于验证失败的 AJAX 请求。

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

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

【讨论】:

我无意中在提交按钮上省略了提交全部 ID。即使有 id,它也只是停留在页面上。加载资源失败:服务器响应状态为 419(未知状态) 有几个问题,我已经更新了我的答案来解决所有这些问题。 感谢您的意见@Don't Panic。我在这里更新了我当前的代码,因为我仍然面临同样的问题。 @Enovyne 您更新的代码对我有用,尽管我没有测试您的控制器代码,只是文件已正确发布并且服务器接收到预期的数据。 "display argument supplied for foreach()" 不是我见过的错误信息,也没有出现在 Google 中。它真的是你所看到的,以及抛出它的东西,php 还是 JS?另外,您确定正在使用正确的控制器/方法吗?浏览器开发工具显示什么(检查网络和控制台)? 错误消息“为 foreach() 提供的参数不再显示。”那是针对PHP代码的。在控制台中,显示加载资源失败:服务器响应状态为 419(未知状态),这很奇怪。它只是停留在页面上。

以上是关于无法将附件传递给控制器​​:422 Unprocessable Entity的主要内容,如果未能解决你的问题,请参考以下文章

无法将 iframe 元素从指令传递给 Angular 控制器

似乎无法将表单值(在视图中)传递给控制器

无法识别的选择器发送到实例...使用 segues 将字符串传递给另一个视图控制器

C# ASP.net MVC Ajax MySQL DATATABLES 列搜索无法将搜索值传递给控制器

无法快速显示第一个视图控制器将值传递给第二个视图控制器

我无法在操作方法中将我的文件传递给 httppostedfilebase