Ionic 3 post image using form-data - php

I'm trying to post form data, consists of text and image file to PHP server.
I use ionic native camera to get a picture from gallery:
const options: CameraOptions = {
quality: 70,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
saveToPhotoAlbum:false,
targetWidth: 400,
targetHeight: 400
}
this.camera.getPicture(options).then((imageData) => {
this.myphoto = normalizeURL(imageData);
this.myphoto2 = imageData;
}, (err) => {
});
And post it using form data:
var headers = new Headers();
headers.append('Content-Type', 'multipart/form-data;boundary=' + Math.random());
headers.append('Accept', 'application/json');
let options = new RequestOptions({
headers: headers
});
let formData = new FormData();
formData.append('judul', this.judul.value);
formData.append('photo', this.myphoto, '123.jpg');
this.http.post('http://localhost/upload.php', formData, options)
.map(...)
.subscribe(...);
But, I saw on PHP log, the form-data not sent by ionic.
What's wrong here?

You can try removing 'options' from the this.http.post() arguments.
Your code becomes :
this.http.post('http://localhost/upload.php', formData)
.map(...)
.subscribe(...);
If this doesn't work,
try sending across the entire BASE64 Image using
'destinationType: this.camera.DestinationType.DATA_URL'

i advise you use the native plugin to upload file :
https://ionicframework.com/docs/native/file-transfer/

First Take Photo From Camera
async takePhoto() {
const options: CameraOptions = {
quality: 70,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
saveToPhotoAlbum:false,
targetWidth: 400,
targetHeight: 400
}
this.camera.getPicture(options).then((imageData) => {
this.getSystemURL(imageData);
}, (err) => {
});
}
Than Get a Local System Image URL
private getSystemURL(imageFileUri: any): void {
this.file.resolveLocalFilesystemUrl(imageFileUri)
.then(entry => (entry as FileEntry).file(file => {
this.readFile(file);
}))
.catch(err => console.log(err));
}
After Read That Image URL
private readFile(file: any) {
const reader = new FileReader();
reader.onloadend = () => {
this.myphoto = new Blob([reader.result], {type: file.type});
var headers = new Headers();
headers.append('Content-Type', 'multipart/form-data;boundary=' + Math.random());
headers.append('Accept', 'application/json');
let options = new RequestOptions({
headers: headers
});
let formData = new FormData();
formData.append('judul', this.judul.value);
formData.append('photo', this.myphoto, '123.jpg');
this.http.post('http://localhost/upload.php', formData, options)
.map(...)
.subscribe(...);
};
reader.readAsArrayBuffer(file);
}
It is working for me,
Hope it will help.

Related

GETTING ERROR POSTING FILE TO MYSQL - PHP-CRUD-API

I'm trying to upload an image using mevdschee's PHP-CRUD-API.
I've tried almost everything..
theese are the service functions I've tried, using both FormData or simple json.
service.ts
addMapIcon(mapIcon:mapIcon): Observable<string>{
let fd = new FormData;
fd.append('active', mapIcon.active?'1':'0');
fd.append('file',mapIcon.file);
fd.append('name',mapIcon.name);
return this.http.post<string>(this.iconApiUrl, fd);
..or even:
return this.http.post<string>(this.iconApiUrl, fd, {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Content-type':'multipart/form-data'
+ combination of others parameters
}));
}
addMapIcon(mapIcon:mapIcon): Observable<string>{
return this.http.post<string>(this.iconApiUrl, mapIcon, {
headers: new HttpHeaders({
'Content-Type': 'application/json',
}),
});
}
component.ts
onIconChange(e) {
const reader = new FileReader();
if(e.target.files && e.target.files.length) {
const [file] = e.target.files;
reader.readAsDataURL(file);
reader.onload = () => {
this.mapIcon.file = file; //(or even reader.result as string; as found in some example)
this.mapIcon.name = file.name;
this.mapIcon.active = true;
//this.icon.file = file;
/*this.uploadForm.patchValue({
imgSrc: reader.result
});*/
};
}
}
the file field is defined as mediumblob in mysql.
The error I get is "Data integrity violation".
Can't understand where the error is..
The "Data integrity violation" error is caused by a failing constraint. This may be:
a foreign key constraint that is failing (referenced record does not exist)
a missing field value (on a field without a default value)
a null value where it is not allowed (the field is not nullable)
You may enable debug mode ('debug' => true in the config) and look at the X-Exception-Message HTTP header of the response (using the Network tab of the Developer tools of your browser). It will contain the cause of the problem.
NB: I am "mevdschee", the author of the PHP-CRUD-API.
are you able to send image blob successfully to backend using post request? If not try this :
addMapIcon(mapIcon:mapIcon): Observable<string>{
let fd = new FormData();
fd.append('active', mapIcon.active?'1':'0');
**fd.append('file',mapIcon.file, mapIcon.name);**
fd.append('name',mapIcon.name);
return this.http.post<string>(this.iconApiUrl, fd, {
headers: new HttpHeaders({
'Content-type':'multipart/form-data'
}));
}

How to get file from Form Data in the server

I cant get the file data on the server. _$FILE says is empty. I do this trough ionic app. I send the information in http params.
cargarFoto(idnegocio,formData) {
let datos = new HttpParams()
.set("proceso", "subirImgNegocioApp")
.set("imgRestaurante", formData)
.set("idnegocio", idnegocio)
let headerOptions = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post(this.path,datos, {
observe: 'response',
responseType: 'text',
headers: headerOptions
});
}
That is the code from my service where i send the form Data and other information.
But when i use $_FILES to get the file, it says is null or empty. What im doing wrong? Actually all the information is get on $_POST. I returned post to the app and this is what displays:
body: "{
"proceso": "subirImgNegocioApp",
"imgRestaurante": "[object FormData]",
"idnegocio": "4"
}"
I can suggest little different approach - send everything as form data:
sendSomething(someVar: string, files: File[]) {
const formData = new FormData();
for (const f of files) {
formData.append('file[]', f);
}
formData.append('someVar', someVar);
return this.http.post('/someUrl', formData, {
headers: new HttpHeaders({ enctype: 'multipart/form-data' })
});
}
Then in PHP:
$someVar = $_REQUEST['someVar']
And files (or one file) will be in
$_FILES['file']

React Native uploading Image to php page on server

I have PHP page on a web server to upload image from React Native.
Using Postman method POST, form-data key:avatar value: image_file everything works as expected.
In React Native I tried:
let uploadData = new FormData();
uploadData.append('avatar', uploadUri);
fetch(base_url, { method: 'post,', body: uploadData }).then(
(res) => {
var myresponse = res;
console.log(JSON.stringify(myresponse));
//console.log(res);
}
);
I am getting from server error:
{"type":"default","status":400,"ok":false,"headers":{"map":{"server":"Apache","connection":"Upgrade,
close","content-type":"text/html","vary":"Accept-Encoding,User-Agent","date":"Wed,
20 May 2020 15:29:15
GMT","accept-ranges":"bytes","upgrade":"h2,h2c"}},"url":"http://www./uploadImage.php","_bodyInit":{"_data":{"size":10154,"offset":0,"blobId":"D8041FEE-0479-4CD5-8438-4EFD737561DE","type":"text/html","name":"uploadImage.php","__collector":{}}},"_bodyBlob":{"_data":{"size":10154,"offset":0,"blobId":"D8041FEE-0479-4CD5-8438-4EFD737561DE","type":"text/html","name":"uploadImage.php","__collector":{}}}}
Than I tried using axios:
let uploadData = new FormData();
uploadData.append('avatar', uploadUri);
axios.post(base_url, uploadData).then((res) => {
console.log(res);
});
I get this response from the server:
"error": true,
"message": "No file was sent!",
"status": "error",
It is failing on: if($_FILES['avatar']), in PHP.
I have no idea what to do any more, again in Postman everything works fine as expected.
Does anybody have any idea what to do?
I tested it again and it is to be a problem with the URI that I am sending, for sure.
ie. if I look in Postman the request that I am sending:
avatar=#/Users/......image.jpg
and in React Native I am sending:
"avatar","file:///Users/.....image.jpg
By the way, I am using expo-image-picker to select the image.
It looks like this did the work..
let body = new FormData();
//Appending file to body
body.append('avatar', {
uri: uploadUri,
type: 'image/jpeg', //This is the file type .. you can define according to your requirement
name: 'avatar.jpg', //File name you want to pass
});
//Service call
fetch(base_url, {
method: 'POST',
headers: new Headers({
'Content-Type': 'application/x-www-form-urlencoded',
}),
body: body,
})
.then((res) => res.json())
.then((responseJson) => {
//GET RESPONSE SUCCESS OF FAILURE
console.log(JSON.stringify(responseJson));
})
.catch((error) => {
//ERROR
console.log(JSON.stringify(error));
});

Angular 5 and PHP can't use the POST method to send a value to server scripts

I am having a problem using post method in Angular 5 and PHP.
I have this method from a .ts class:
addPartners(partnerName)
{
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
this.name = JSON.stringify(partnerName)
console.log("hi "+ this.name)
return this.http.post('http://aff.local/addPartner.php', this.name, {
observe: 'response',
responseType: 'json'
}).pipe(map(
res=>{
console.log(res)
}
))
}
And I will call it on (click) event of a button:
addPartner(){
this.email = this.subscribeForm.get('emailTxt').value;
//console.log(this.email)
this.api.addPartners(this.email).subscribe(
(data)=>{
console.log(data);
this.subscribeForm.reset();
},
(error)=>{
console.log(error)
}
);
}
The PHP script is :
addPartner($partnerName);
echo $result;
?>
When I fill the textbox and click on the button, the value sent is empty.
When I change the method, by sending the variable in the url it work properly.
Here is the working script. In the api main class:
addPartners(partnerName)
{
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
this.name = JSON.stringify(partnerName)
console.log("hi "+ name)
return this.http.post('http://aff.local/addPartner.php?name='+ name, {
observe: 'response',
responseType: 'json'
}).pipe(map(
res=>{
console.log(res)
}
))
}
I just changed the url into:
http://aff.local/addPartner.php?name='+ name,
And in the php script I will get it using $_REQUEST['name'].
What I want is using the POST method because I need to send multiple data from a form.
if you want to use JSON.stringify so you can take params from the server side using :
$request_body = file_get_contents('php://input');
$data = json_decode($request_body);
or if we want to just take data using $_POST['paramName'] so we have to use the below in your client side:
let headerOptions = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
let data = {name: partnerName};
let body = this.formatData(test);
and format your data like that:
formatData(data) {
let returnData = '';
let count = 0;
for (let i in data) {
if (count == 0) {
returnData += i + '=' + data[i];
} else {
returnData += '&' + i + '=' + data[i];
}
count = count + 1;
}
return returnData;
}
In the POST-example you used this.name, but in the GET-example only name.
Try to use $_POST['name'] instead of $_REQUEST['name], because $_REQUEST['name] is a different variable then $_POST or $_GET and also differently treated.

How to post JSON data to another server by lambda script

I am trying to send some JSON data(Fetched From DaynamoDB) to another server from AWS lambda function but while giving the URL in the script :
'use strict';
const https = require('https');
exports.handler = (event, context, callback) => {
var options = {
hostname: 'https://www.corecomputersystem.com',
path: '/getSyncData.php',
port : 432,
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
};
event.Records.forEach((record) => {
console.log(record.eventID);
console.log(record.eventName);
console.log('DynamoDB Record: %j', record.dynamodb);
var res = record.dynamodb;
const req = https.request(options, (res) => {
let body = "";
console.log('Status:', res.statusCode);
console.log('Headers:', JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', (chunk) => body += chunk);
res.on('end', () => {
console.log('Successfully processed HTTPS response');
// If we know it's JSON, parse it
if (res.headers['content-type'] === 'application/json') {
body = JSON.parse(body);
}
callback(null, body);
});
});
req.on('error', callback);
req.write(JSON.stringify(event.data) + "");
req.end();
//context.succeed();
});
};
it's throwing following error,
{
"errorMessage": "getaddrinfo ENOTFOUND https://www.corecomputersystem.com https://www.corecomputersystem.com:432",
"errorType": "Error",
"stackTrace": [
"errnoException (dns.js:26:10)",
"GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:77:26)"
]
}
and if I uncomment the context.succeed(), there is no error, I need help for identifying the error.
Just for deeply with #at0mzk says, a hostname never take any port number, so any prefix like [http, https, smb, nfs]:// will throw an error any where a hostname is requested.
(http://localhost === localhost:80)
remove https:// from hostname variable.
var options = {
hostname: 'www.corecomputersystem.com',
path: '/getSyncData.php',
port : 432,
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
see docs.
Before making HTTPS request we can use :
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
so it will not ask for authorization.
Another way we can add a key in option before requesting HTTP:
rejectUnauthorized: false
It will not ask for self asigned certificate.
This is what I was searching for.
This worked for me.
In lambda use the following node js.
const https = require('https');
var querystring = require("querystring");
const doPostRequest = (event) => {
//parameters to post
const params = {
name: "John",
title: "Developer",
userid: 123
};
var qs = querystring.stringify(params);
var qslength = qs.length;
return new Promise((resolve, reject) => {
const options = {
host: 'example.com',//without https or http
path: '/yourpath/yourfile.php',
method: 'POST',
port: 443, // replace with 80 for HTTP requests
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': qslength
}
};
var buffer = "";
//create the request object with the callback with the result
const req = https.request(options, (res) => {
resolve(JSON.stringify(res.statusCode));
res.on('data', function (chunk) {
buffer+=chunk;
});
res.on('end', function() {
console.log(buffer);
});
});
// handle the possible errors
req.on('error', (e) => {
reject(e.message);
});
//do the request
req.write(qs);
//finish the request
req.end();
});
};
exports.handler = async (event) => {
try {
const result = await doPostRequest(event);
console.log('result is:️ ', result);
//️️ response structure assume you use proxy integration with API gateway
return {
statusCode: 200,
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(result),
};
} catch (error) {
console.log('Error is:️ ', error);
return {
statusCode: 400,
body: error.message,
};
}
};
For some reason lambda didnt show the response for me other than 200. So I had to create a logfile on my server to verify that it was sending the POST values. From there you can use json_encode to show the posted string or just echo the POST values
$inputJSON = json_encode($_POST);
$input = json_decode($inputJSON, TRUE);
$log = "Data: ".$_SERVER['REMOTE_ADDR'].' - '.date("F j, Y, g:i a").PHP_EOL.
"Data: ".$inputJSON.PHP_EOL.
"Data: ".$input.PHP_EOL.
"Data: ".$_POST['name'].PHP_EOL.
"Data: ".$_POST['title'].PHP_EOL.
"Data: ".$_POST['userid'].PHP_EOL.
"-------------------------".PHP_EOL;
//Save string to log, use FILE_APPEND to append.
file_put_contents('./log_'.date("j.n.Y").'.log', $log, FILE_APPEND);

Categories