繁体   English   中英

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

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

我发送的请求包括表单数据对象,其中包含一些从 angular 4 到 laravel api 的数据......有时请求数据被正确接收,其他时候请求为空“空请求”

这是我的请求详细信息

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

请求有效载荷

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

这是从 laravel 返回到控制台的请求的屏幕截图

更新

这是我的代码

角边:

这里的表单数据对象是角度表单数据对象

 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 ] );

接口:

 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() ); }

侧边

路线

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

控制器文件

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

这是 PHP 的问题。

除非请求方法是 POST,否则它不会解析多部分表单数据:

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

解决方案:

有很多解决方法,没有一个是整洁的,但是:

  1. 使用 PATCH/PUT 以获得最佳实践,或者只是简单地 POST 用于演示场景。

  2. 如果您不能切换方法,那么只需从不使用 Formdata 重新编写代码,PHP 就会正确处理文件。

  3. 使用 POST 发送并添加 _method:put on formData

(3) 像这样:

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

我通过 JavaScript 使用 Axios 遇到了这个问题,因为内容类型标头是 multipart-form-data 但缺少边界。

根据我的研究,处理它的一个好方法是允许 Axios 自动检测内容类型并自行正确设置标题。

这是如何实现这一点的想法:

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;

上面的代码在一个通用的 handleSubmit 函数中,可以从客户端的任何地方调用。

这是函数签名:

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

在上面的代码中,有两个用例。 第一种是默认情况,其中通过平面对象发送正常有效负载。 第二种情况是表单有文件并且您想要multipart/form-data 在这种情况下,我们使用FormData对象作为容器来指示 Axios 自动检测必要的标题并设置正确的边界。

如果您没有正确指定标头,则可能会在 Laravel 中收到一个空的$request->all()数组。

我的答案的简短回答是使用FormData对象,因为它比普通的旧 JavaScript 对象包含更多信息。 有了它,您还可以访问:

const formData = new FormData();

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

正如我上面的注释所暗示的那样,使用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