简体   繁体   中英

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'

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

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.

It does not parse multi part form data unless the request method is POST:

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.

  2. If you can't switch method, then simply rework the code from not using Formdata and PHP will process the file properly.

  3. Send with POST and add _method:put on formData

(3) Like so:

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.

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.

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.

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

If you do not specify the headers correctly, it is possible to receive an empty $request->all() Array in Laravel.

The short answer to my answer is to use the FormData Object because it contains more information than a plain-old-JavaScript-object. 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.

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

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

检查php.ini file_uploadsupload_max_filesizepost_max_size指令。

你应该这样使用:

$request->file('filename')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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