Empty $request->request and $request->files with multipart/form-data - php

I am trying to upload a form with a file to my server using AJAX, but Symfony doesn't parse the request body like it should. This is my PHP:
#[Route('/api/upload/file', name: "api_upload_file", methods: ['POST'])]
public function create(Request $request): JsonResponse
{
dump($request->files->all());
dump($request->request->all());
dump($request->getContent());
...
and the dump output (The file part is cut out because it takes a lot of space) :
[]
[]
"""
------WebKitFormBoundaryh4t0I09h9iTRNGme
Content-Disposition: form-data; name="subcategory"
1
------WebKitFormBoundaryh4t0I09h9iTRNGme
Content-Disposition: form-data; name="main_image"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryh4t0I09h9iTRNGme
Content-Disposition: form-data; name="more_images"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryh4t0I09h9iTRNGme
Content-Disposition: form-data; name="original_version"
------WebKitFormBoundaryh4t0I09h9iTRNGme
Content-Disposition: form-data; name="version"
------WebKitFormBoundaryh4t0I09h9iTRNGme
Content-Disposition: form-data; name="original_title"
------WebKitFormBoundaryh4t0I09h9iTRNGme
Content-Disposition: form-data; name="title"
"""
The request clearly gets through so I do not understand why the content is not parsed
Just in case, here is the javascript part : (This looks like JQuery but is not)
form.submit(e => {
e.preventDefault();
let formData = createItemForm.formData();
$.ajax('/api/upload/file', {
headers: {
'Content-Type': 'multipart/form-data'
},
body: formData
})
.then(data => data.json())
.then(json => {
console.log('uploaded');
});
});
How should I do to get the files and the form values in $request->files and $request->request ?

DO NOT specify the Content-Type header yourself, when trying to make such a multipart request. That header needs to include the boundary value (so that the receiver will know how to parse this request) - if you specify it yourself, as just multipart/form-data, then that will be missing.
These request libraries usually know how to properly set it on their own, based on that you are passing in a FormData instance.

Related

What is the equavalent of php getallheaders() function in Angular 4/5?

What is the equavalent of php getallheaders() function in Angular 4/5 ?
I need to get request headers but i can't find this in Angular. I can get only response headers with Angular.
I need to get request header parameters when application start not sending get or post request. In picture i need X-MSISDN and X-IMSI parameters
I try Interceptor class but its only works when i send get or post requests.
Explanation:
I open application with this url : http://localhost:4200/#/
In this time my request header is like this:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7
Cache-Control: no-cache
Connection: keep-alive
Cookie: s_fid=07C355F600B90B3D-291EBB86E5858A2F; s_cc=true; gdslv_s=Less%20than%201%20day; s_vnum=1556196774798%26vn%3D7; s_invisit=true; s_ppvl=login%2520sayfasi%2C100%2C100%2C933%2C375%2C667%2C375%2C667%2C2%2CLP; s_ppv=Welcome%253Atarife%253Aanasayfa%2C100%2C100%2C667%2C375%2C667%2C375%2C667%2C2%2CP; s_ppn=Welcome%3Atarife%3Aanasayfa; gdslv=1524831169979; s_getNewRepeat=1524831169981-Repeat; utag_main=v_id:0162fcdd2735001117d070e941e904072002406a00918$_sn:7$_ss:0$_st:1524832969982$_pn:2%3Bexp-session$ses_id:1524831079859%3Bexp-session$_prevpage:Welcome%3Atarife%3Aanasayfa%3Bexp-1524834769972
Host: localhost:4200
Pragma: no-cache
Referer: http://localhost:4200/
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1
X-IMSI: 286026134103281
X-MSISDN: 905499914581
Request URL : http://localhost:4200/sockjs-node/info?t=1524831359435
I need to take X-IMSI and X-MSISDN parameters.
Following my comment : you could create a service that is in charge of handling all of your headers. That's also a good practice : you centralize the logic of a feature.
Here is an instance of a service that can do that. It can create JSON headers, append new headers to the list, reset them ... See for yourself.
import { Injectable } from '#angular/core';
import { Headers } from '#angular/http';
#Injectable()
export class HeadersManagerService {
private headers: Headers;
constructor() {
this.resetHeaders();
}
resetHeaders() {
this.headers = new Headers();
}
newHeader(key, value) {
this.headers.append(key, value);
}
createJsonHeaders() {
this.resetHeaders();
this.headers.append('Content-Type', 'application/json');
}
getHeaders() {
return this.headers;
}
}
PS: Posting as an answer because it's too long for a comment.
Why don't you try like this
setHeaders() {
const headers = new Headers({
'Content-Type': 'application/x-www-form-urlencoded'
});
const options = new RequestOptions({ headers: headers });
console.log(options.headers);
// return options;
}
In angular if it is object, for example
obj{name:"ABC" , role:"Student"} then Object.keys(obj); will return headers

Receiving a string value from client to server

I am working on Android along with yii-2 php. From my app I am sending some photos in a file using an api call. Along with it I am sending a reference number as shown below.
#Multipart
#POST("installation/photo/save")
Call<ApiResponse> uploadImage(#Header("Authorization") String token, #Part("ref_no") RequestBody ref_no, #Part MultipartBody.Part file);
The call is initialized as shown below
Retrofit retrofit = RetrofitClient.getClient();
RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class);
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("uploaded_file", file.getName(), requestFile);
RequestBody ref_no = createPartFromString("<ref_no>");
ref_no = createPartFromString(installationDetails.getReferenceNo());
Call<ApiResponse> call = retrofitInterface.uploadImage("Bearer " + Common.getAuthKey(mContext),ref_no, body);
call.enqueue(new Callback<ApiResponse>() {
#Override
public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) {
if (response.isSuccessful()) {
Log.d(TAG, response.body().getStatus());
if (response.body().getStatus().equals("OK")) {
snapManager.updateSnapStatus(AssetsManagementContract.SnapEntry.COLUMN_SITE_SNAP, snap.getSnapName(), Constants.SNAP_SYNCED);
Intent broadcastSyc = new Intent();
broadcastSyc.setAction(Common.GetSyncImageAction());
broadcastSyc.putExtra("STATUS", true);
mContext.sendBroadcast(broadcastSyc);
sendImage(mContext);
}
else{
snapManager.updateSnapStatus(AssetsManagementContract.SnapEntry.COLUMN_SITE_SNAP, snap.getSnapName(), Constants.SNAP_CLOSED);
}
} else {
snapManager.updateSnapStatus(AssetsManagementContract.SnapEntry.COLUMN_SITE_SNAP, snap.getSnapName(), Constants.SNAP_CLOSED);
Log.d(TAG, "Error");
}
}
Working of app
User note down the details of installation and take pictures
On closing the form two API's are called
i) API to save/upload installation data to server
ii) API to save/upload images to the server.
The images are uploaded when the Installation API response is returned OK.
OkHttp Log
When the images are pushed to the server below is the call in ok http
--> POST http://ip:port/api/web/v1/installation/photo/save
01-31 08:34:14.723 5762-6086/com.thumbsol.accuratemobileassetsmanagament D/OkHttp: Content-Type: multipart/form-data; boundary=704cd1e5-e4d5-4d2e-be63-81f5fe3f1aef
01-31 08:34:14.723 5762-6086/com.thumbsol.accuratemobileassetsmanagament D/OkHttp: Content-Length: 116027
01-31 08:34:14.724 5762-6086/com.thumbsol.accuratemobileassetsmanagament D/OkHttp: Authorization: Bearer key
01-31 08:34:14.745 5762-6086/com.thumbsol.accuratemobileassetsmanagament D/OkHttp: --704cd1e5-e4d5-4d2e-be63-81f5fe3f1aef
01-31 08:34:14.747 5762-6086/com.thumbsol.accuratemobileassetsmanagament D/OkHttp: Content-Disposition: form-data; name="ref_no"
01-31 08:34:14.748 5762-6086/com.thumbsol.accuratemobileassetsmanagament D/OkHttp: Content-Transfer-Encoding: binary
01-31 08:34:14.748 5762-6086/com.thumbsol.accuratemobileassetsmanagament D/OkHttp: Content-Type: multipart/form-data; charset=utf-8
01-31 08:34:14.754 5762-6086/com.thumbsol.accuratemobileassetsmanagament D/OkHttp: Content-Length: 15
01-31 08:34:14.755 5762-6086/com.thumbsol.accuratemobileassetsmanagament D/OkHttp: 28372250046142R //this is reference number
01-31 08:34:14.755 5762-6086/com.thumbsol.accuratemobileassetsmanagament D/OkHttp: --704cd1e5-e4d5-4d2e-be63-81f5fe3f1aef
01-31 08:34:14.755 5762-6086/com.thumbsol.accuratemobileassetsmanagament D/OkHttp: Content-Disposition: form-data; name="uploaded_file"; filename="28372250046142R_1517369623_site_1.jpg"
01-31 08:34:14.755 5762-6086/com.thumbsol.accuratemobileassetsmanagament D/OkHttp: Content-Type: multipart/form-data
01-31 08:34:14.755 5762-6086/com.thumbsol.accuratemobileassetsmanagament D/OkHttp: Content-Length: 115567
Server Side
At server side below is API code through which images are saved.
public function actionSavephoto()
{
try {
$count = 0;
foreach ($_FILES as $f) {
$dd = pathinfo($f['name']);
if (!isset($dd['extension']) || !in_array($dd['extension'], array('jpg', 'png', 'gif'))) {
return ['status' => 'ERROR', 'uploaded_files' => $count, 'message' => 'Invalid File'];
break;
}
if (move_uploaded_file($f['tmp_name'], Installations::UPLOAD_FOLDER . $f['name'])) {
$count++;
return ['status' => 'OK', 'uploaded_files' => $count];
break;
} else {
return ['status' => 'ERROR', 'uploaded_files' => $count];
break;
}
}
} catch (Exception $x) {
return ['status' => 'ERROR', 'message' => $x->getMessage()];
}
}
The response after var_dump($dd) below is the response that generates.
array(4) {
["dirname"]=>
string(1) "."
["basename"]=>
string(37) "28372230019211U_1517370655_site_1.jpg"
["extension"]=>
string(3) "jpg"
["filename"]=>
string(33) "28372230019211U_1517370655_site_1"
}
In response there is no reference number. How can I get the reference number at server side?
Any help would be highly appreciated.
Check if there is $_POST['ref_no'] present at server side after the call.

Setup sending post request from android to php script

Android Retrofit's servise interface:
//#Headers("Authorization: " + BuildConfig.CLIENT_NAME + " " + BuildConfig.CLIENT_PASSWORD)
#FormUrlEncoded
#POST("api/post/report")
Observable<Object> postReport(#Field("message") String message);
Android monitor tells:
--> POST http://<mysite>/api/post/report http/1.1
D/OkHttp: Content-Type: application/x-www-form-urlencoded
D/OkHttp: Content-Length: 104
D/OkHttp: message=%D0%B2%D0%BB%D0%BE%D1%81%D0%B8%3A%20%D1%81%D0%BB%D1%87%D0%BB%D1%8C%D1%8F%D0%B1%D1%8B%D0%B6%D1%8B
D/OkHttp: --> END POST (104-byte body)
I do not know how to catch the Message from PHP.
$_POST - is empty
parse_str(file_get_contents("php://input"), $data);
$data = (object)$data;
Different variants of ^ are also not working. They returns nullable results, empty objects and ext
You are making a POST request.
print_r($_POST);
Should give you the value sent from retrofit.
Ok.ok. I did this:
//#Headers("Authorization: " + BuildConfig.CLIENT_NAME + " " + BuildConfig.CLIENT_PASSWORD)
#POST("api/post/report")
Observable<Object> postReport(#Header("message") String message);
I sent this via Header & catched the message with getHeaders() method...

Fails to send cookies on http request

I have vbscript code that send an ajax request to server with cookie using MSXML2.XMLHTTP object. I have read about this bug and workaround. By invoking setRequestHeader twice, cookies should properly sent..but that not happening..
The vbscript code:
Dim http
set http = WScript.CreateObject("MSXML2.XMLHTTP")
http.open "POST", "http://localhost/echo", false
http.setRequestHeader "X-Requested-With", "XMLHttpRequest"
http.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
http.setRequestHeader "Cookie", "SESSID=f3rds19k7qu58pvmb80561dc76" '1st invoke '
http.setRequestHeader "Cookie", "SESSID=f3rds19k7qu58pvmb80561dc76" '2nd invoke '
http.send sReq
msgbox http.responseText
And on server side at http://localhost/echo/index.php contains code
<?php print_r(getallheaders());?>
that php code basically only echoing the request header back to the client, and even I invoke twice this what I got:
Array
(
[Accept] => */*
[X-Requested-With] => XMLHttpRequest
[Accept-Language] => id
[Accept-Encoding] => gzip, deflate
[User-Agent] => Mozilla/4.0 (bla..bla..bla...)
[Host] => localhost
[Connection] => Keep-Alive
[Cache-Control] => no-cache
)
As you can see no cookie on the header. How to make cookie sent properly to server?
Finally i found solution... simple.. just use WinHTTP.WinHTTPRequest instead of MSXML2.XMLHTTP
Dim http
set http = WScript.CreateObject("WinHTTP.WinHTTPRequest.5.1")
http.open "POST", "http://localhost/echo", false
http.setRequestHeader "X-Requested-With", "XMLHttpRequest"
http.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
http.setRequestHeader "Cookie", "SESSID=f3rds19k7qu58pvmb80561dc76"
msgbox http.responseText

Phonegap Consuming Web Service PHP

The next problem is try to consume a web service. I try with plugins and pure xml but the result still be "NULL".
The code is this.
function soap(imei,clave)
{
var divToBeWorkedOn = "#res";
var webServiceURL = '';
var parameters = '<?xml version="1.0" encoding="utf-8"?> \
<soap:Envelope xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance " xmlns:xsd=" http://www.w3.org/2001/XMLSchema " xmlns:soap=" http://schemas.xmlsoap.org/soap/envelope/"> \
<soap:Body> \
<registra_imei> \
<request> \
<imei>'+imei+'</imei> \
<clave>'+clave+'</clave> \
</request> \
</registra_imei> \
</soap:Body> \
</soap:Envelope>';
$.ajax({
type: "Post",
url: webServiceURL,
data: parameters,
contentType: "text/xml; charset=\"utf-8\"",
dataType: "xml",
success: function(msg) {
alert("funciono "+msg);
},
error: function(e){
alert("error");
}
});
}
The Web services is a simple SOAP PHP. Just I need send the variables and then get a response that will be a code (1, 2 or 3).
The requeriment from the event "registra_imei" are this:
Name: registra_imei
Binding: SOAPBinding
Endpoint:
SoapAction: urn:soapwsdl#registra_imei
Style: rpc
Input:
use: encoded
namespace: urn:soapwsdl
encodingStyle: http://schemas.xmlsoap.org/soap/encoding/
message: registra_imeiRequest
parts:
imei: xsd:string
clave: xsd:string
Output:
use: encoded
namespace: urn:soapwsdl
encodingStyle: http://schemas.xmlsoap.org/soap/encoding/
message: registra_imeiResponse
parts:
return: xsd:int
Namespace: urn:soapwsdl
Transport: http://schemas.xmlsoap.org/soap/http
Documentation: Registra imei
My comment is too long to post it into the comment area.
So, using SoapUI i simulated a call to your WSDL and i got this as a RAW response:
HTTP/1.1 200 OK
Date: Tue, 14 Apr 2015 19:44:24 GMT
Server: LiteSpeed
X-Powered-By: PHP/5.4.39
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Set-Cookie: PHPSESSID=870fgce5tm1ep8get75066i491; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Content-Length: 0
This is the SOAP request:
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:soapwsdl">
<soapenv:Header/>
<soapenv:Body>
<urn:registra_imei soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<imei xsi:type="xsd:string">65656565</imei>
<clave xsi:type="xsd:string">123</clave>
</urn:registra_imei>
</soapenv:Body>
</soapenv:Envelope>
RAW request:
POST http://soap.movilaccesscloud.cl/serversoap.php/ HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: "urn:soapwsdl#registra_imei"
Content-Length: 508
Host: soap.movilaccesscloud.cl
Proxy-Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
Apparently, the error is in the back-end of your webservice. Check your PHP code, if possible please share part of the code.
I repeat, my intention was to put the comment in the proper area, but as you can see it´s too long.
:)

Categories