简体   繁体   English

Laravel $request->all() 使用 multipart/form-data 为空

[英]Laravel $request->all() is empty using multipart/form-data

I'm sending request includes form data object with some data from angular 4 to laravel api ... sometimes request data is received correctly, other times request is null 'empty request'我发送的请求包括表单数据对象,其中包含一些从 angular 4 到 laravel api 的数据......有时请求数据被正确接收,其他时候请求为空“空请求”

and here is my request details这是我的请求详细信息

Accept:application/json
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.9
Authorization:Bearer ---------
Connection:keep-alive
Content-Length:973
Content-Type:multipart/form-data; boundary=----WebKitFormBoundarydEkuATdI8JBFdnBM
Host:127.0.0.1:8000
Origin:http://localhost:4200
Referer:http://localhost:4200/shop_admin
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36

Request Payload请求有效载荷

------WebKitFormBoundarydEkuATdI8JBFdnBM
Content-Disposition: form-data; name="business_id"

249
------WebKitFormBoundarydEkuATdI8JBFdnBM
Content-Disposition: form-data; name="maintenance_flag"

0
------WebKitFormBoundarydEkuATdI8JBFdnBM
Content-Disposition: form-data; name="type"

shop
------WebKitFormBoundarydEkuATdI8JBFdnBM
Content-Disposition: form-data; name="name"

qewqweqweqwe
------WebKitFormBoundarydEkuATdI8JBFdnBM
Content-Disposition: form-data; name="website_uri"


------WebKitFormBoundarydEkuATdI8JBFdnBM
Content-Disposition: form-data; name="phone_number"


------WebKitFormBoundarydEkuATdI8JBFdnBM
Content-Disposition: form-data; name="facebook_link"


------WebKitFormBoundarydEkuATdI8JBFdnBM
Content-Disposition: form-data; name="logo_uri"

uploads/businesses/249/249_1.jpg
------WebKitFormBoundarydEkuATdI8JBFdnBM
Content-Disposition: form-data; name="brands"

undefined
------WebKitFormBoundarydEkuATdI8JBFdnBM--

here is a screenshot for request back from laravel into console这是从 laravel 返回到控制台的请求的屏幕截图

UPDATE更新

here is my code这是我的代码

angular side:角边:

form data object here is angular form data object这里的表单数据对象是角度表单数据对象

 let formData: FormData = new FormData(); formData.append( 'business_id', that.businessId ); formData.append( 'maintenance_flag', that.maintenance_flag ); formData.append( 'type', edit_type ); formData.append( 'name', name ); formData.append( 'website_uri', website ); formData.append( 'phone_number', phone ); formData.append( 'facebook_link', face ); formData.append( 'logo_uri', that.basicData.logo_uri ); formData.append( 'brands', that.selectedBrands ); if ( pic.files.length > 0 ) formData.append( 'logo_uri', pic.files[ 0 ] );

api:接口:

 that.apiService.changeBusiness( formData ).subscribe( ( res ) => { console.log( res ); } shopUpdate ( shop_basic_info ){ return this.http.post( environment.api_base_url + 'api/shop_update', shop_basic_info ).map( res => res.json() ); }

laravel side侧边

Route路线

 Route::post('/shop_update', 'ShopController@handleUpdate');

controller file控制器文件

 public function handleUpdate(Request $request) { return $request->all(); }

This is a problem with PHP.这是 PHP 的问题。

It does not parse multi part form data unless the request method is POST:除非请求方法是 POST,否则它不会解析多部分表单数据:

https://bugs.php.net/bug.php?id=55815 https://bugs.php.net/bug.php?id=55815

Solution:解决方案:

There are many workarounds, none with is tidy but:有很多解决方法,没有一个是整洁的,但是:

  1. Use PATCH/PUT for best practice, or just simply POST for demo scenarios.使用 PATCH/PUT 以获得最佳实践,或者只是简单地 POST 用于演示场景。

  2. If you can't switch method, then simply rework the code from not using Formdata and PHP will process the file properly.如果您不能切换方法,那么只需从不使用 Formdata 重新编写代码,PHP 就会正确处理文件。

  3. Send with POST and add _method:put on formData使用 POST 发送并添加 _method:put on formData

(3) Like so: (3) 像这样:

formData.append('_method', 'PUT')

I was getting this problem with Axios via JavaScript because the content-type header was multipart-form-data but the boundary was missing.我通过 JavaScript 使用 Axios 遇到了这个问题,因为内容类型标头是 multipart-form-data 但缺少边界。

Based on my research, a good way to handle it is to allow Axios to auto-detect the content type and set the headers correctly itself.根据我的研究,处理它的一个好方法是允许 Axios 自动检测内容类型并自行正确设置标题。

Here is an idea for how to accomplish this:这是如何实现这一点的想法:

const formDataWithFiles = hasFiles ? new FormData() : undefined;

if (formDataWithFiles) {
    // axios will automatically set the content-type to multipart/form-data if the
    // data param is a FormData object
    // otherwise, it will use application/json
    // (study the Dev Tools > Network tab > XHR tab headers)
    Object.keys(modifiedFields)
        .forEach(field => formDataWithFiles.append(field, modifiedFields[field]));
}

const { data } = await axios({
    method,
    url: actionUrl,
    data: hasFiles ? formDataWithFiles : modifiedFields,
    headers: {
        ...axios.defaults.headers,
        ...headers,
    },
});

return data;

The above code is in a generic handleSubmit function that can be called from anywhere in the client-side.上面的代码在一个通用的 handleSubmit 函数中,可以从客户端的任何地方调用。

Here is the function signature:这是函数签名:

const { data } = await this.submitForm({
    actionUrl: this.actionUrl,
    method: this.method,
    modifiedFields: {
        ...this.modifiedUser,
    },
    hasFiles: true,
});

In the above code, there are two use cases.在上面的代码中,有两个用例。 The first is the default case, where a normal payload is sent via a flat object.第一种是默认情况,其中通过平面对象发送正常有效负载。 The second is the case when the form has files and you want multipart/form-data .第二种情况是表单有文件并且您想要multipart/form-data In this case, we use the FormData Object as a vessel to instruct Axios to auto-detect the necessary headers and set the correct boundary.在这种情况下,我们使用FormData对象作为容器来指示 Axios 自动检测必要的标题并设置正确的边界。

If you do not specify the headers correctly, it is possible to receive an empty $request->all() Array in Laravel.如果您没有正确指定标头,则可能会在 Laravel 中收到一个空的$request->all()数组。

The short answer to my answer is to use the FormData Object because it contains more information than a plain-old-JavaScript-object.我的答案的简短回答是使用FormData对象,因为它比普通的旧 JavaScript 对象包含更多信息。 With it, you can also access:有了它,您还可以访问:

const formData = new FormData();

console.log('boundary:', formData._boundary);

As my annotation above hints towards, use the Dev Tools > Network tab > XHR tab to examine your request headers and make sure you have content-type application/json or application/x-www-form-urlencoded for regular form submits and multipart/form-data' if you are uploading a file.正如我上面的注释所暗示的那样,使用Dev Tools > Network 选项卡 > XHR 选项卡检查您的请求标头,并确保您有内容类型application/jsonapplication/x-www-form-urlencoded用于常规表单提交和multipart/form-data'如果您要上传文件。

您必须将 CSRF 令牌添加到请求添加中: formData.append( '_token', {{csrf_token()}} );

1-除非您的路由不在网络中间件下,否则您需要令牌 2-检查帖子大小,它可能大于允许的最大帖子大小...如果它更大,则必须增加 php.ini 中允许的最大帖子大小。 ini 或 .htaccess 或函数内部

检查php.ini file_uploadsupload_max_filesizepost_max_size指令。

你应该这样使用:

$request->file('filename')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM