Ionic 3 upload image with other fields using POST - javascript

I'm new to this framework, can anyone tell me how to upload an image with other fields in a form to the server using POST?
Currently, I know how to send value from the fields using POST, but without image.
let headers = new Headers({
'Content-Type' : 'application/json'
});
let options = new RequestOptions({ headers: headers });
let data = JSON.stringify({
username: username, password: password
});
return this.http.post(this.baseUrl+"/login/auth", data, options)
.map(res => res.json())
.toPromise()
.catch((error) => {
console.log("Login failed");
return Promise.reject(error);
});

You should use fileTransfer for uploading files, you can send additional data in its options which you can access on your backend.
Other way to do it with http POST is to send base64 data of image , and regenerate it on your backend and save it to location. But that is nonsense , since your post url will be huge, sometimes wont even be able to send it whole.
I would recommend you reading about fileTransfers.

Related

Getting $_POST variable as empty while getting everything correct with php://input

I have created a React application from which I am calling my server built on PHP.
The following is how I call my PHP file:
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: JSON.stringify({ name, username, password }),
};
console.log(requestOptions);
fetch('http://localhost/crud/requests/signup.php', requestOptions)
.then(res => res.json())
.then(data => console.log(data));
Here is what I have in the PHP file:
if (isset($_POST) && !empty($_POST)) {
// do something
}
When I print the $_POST variable, I get an empty array. Even the $_RESPONSE is empty.
But when I tried to print the input stream like this:
print_r(file_get_contents('php://input'));
Everything seems to be fine. Can anyone explain why does this happen?
I tried to read it in the documentation & looked up on some forums and blogs but wasn't satisfied with the answers.
PHP’s built-in form support is only able to parse application/x-www-form-urlencoded forms and multipart/form-data forms. What you are actually sending is a JSON-serialized object, with the incorrect MIME type of application/x-www-form-urlencoded.
To actually send an application/x-www-form-urlencoded form, use URLSearchParams instead of JSON.stringify:
fetch('http://localhost/crud/requests/signup.php', {
method: 'POST',
body: new URLSearchParams({ name, username, password }),
})
.then(res => res.json())
.then(data => console.log(data));
There is no need to set Content-Type explicitly in this case: the browser will do that automatically. To send a multipart/form-data payload (which you may need to do if you want to upload larger files), use a FormData object instead.
If you want to send JSON after all, you should send it with the correct MIME type in the header, application/json. On the PHP side, you will be resigned to parsing the payload manually using json_decode.

JavaScript post Fetch API

I want to post with the Fetch API and call an action from my controller but the action is not being loaded like when I would do it with submitting a post form.
function postQuery() {
let query = document.getElementById("query").value;
fetch('/actionName', {
method: 'POST',
body: query,
headers:
{
"Content-Type": "application/x-www-form-urlencoded"
}
})
.then(response => {
console.log(response);
})
.then(data => {
console.log('Success:', data);
})
}
/actionName is not being loaded, I am supposed to be directed to a different page.
When I would submit a form like that:
<form action="/actionName" method="post">
the public function actionName would be called but with fetch its not working.
When i try to see the $_POST with var_dump($_POST) inside of actionName, I am getting an empty array...I dont understand this
I see two questions here:
Why is the data not accessible to the server
Why is the brower not redirected to /actionName
Answer to #1:
Make sure the content type header matches the data you are sending, if it is raw json, you should use application/json rather then application/x-www-form-urlencoded. If you want to send a form using fetch API, you would need to either serialize to form to a URL encoded format, or use FormData, for example:
var fd = new FormData(document.getElementById('myForm'))
fetch('/actionName', {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data;'
},
body: fd
})
Answer to #2:
Submitting HTML Forms will direct the browser to the forms action, so if I submit a form to /actionName, I will end up seeing the HTML that is returned by the server for that route. Using Fetch API to submit a form is a type of AJAX, which means that it is capable of communicating with the server without needing to load a new page.
With that in mind, you have a few options:
Use a regular form so that the desired default behavior happens
Manually redirect the user somewhere after the fetch promise resolves, something like:
fetch(/*..*/).then(data => {
console.log('Success:', data);
window.location.href = '/otherPage'
})
Render the response HTML without redirecting the user, something like:
fetch(/*..*/).then(data => {
console.log('Success:', data);
data.text().then(rawHTML => {
document.body.parentElement.innerHTML = rawHTML
})
})
My personal intuition would be to go with the first option, as it suits your requirements and is the simplest.

Send file with form-data and axios

I am trying to send a video to a videosite, I am able to upload the video using the REST api and postman, so I know the api works as intended. Now I want to do exatcly the same request using axios. I have code that looks like the example on how to use form-data and axios:
const form = new FormData();
const stream = fs.createReadStream(PATH_TO_FILE);
form.append('image', stream);
// In Node.js environment you need to set boundary in the header field 'Content-Type' by calling method `getHeaders`
const formHeaders = form.getHeaders();
axios.post('http://example.com', form, {
headers: {
...formHeaders,
},
})
.then(response => response)
.catch(error => error)
I get the error that data: 'Content-Length is required'
Any ideas?
May be I got your questions wrong , you want to add Content-Length in the header.
I can see you are uploading video stream. So first you have to calculate the data chunk length.
('Content-Length', File.getSize(stream))
Reference: Can I stream a file upload to S3 without a content-length header?
You can make the post request as multi-part type : 'Content-Type': 'multipart/form-data'.
It is preferable way to send large data to server.
You can check this link : How do I set multipart in axios with react?
If I got your question wrong , plese comment or reply . Thanks
The solution to my problem was to set Content-Length accordingly:
"Content-Length": fs.statSync(filePath)['size']
I think the best way to handle this is to actually use the FormData's own method:
const headers = { 'content-length': formData.getLengthSync(), ...formData.getHeaders() }
This will be more accurate because it includes any other data you may add.
To expound, if you are using a ReadStream, you must use the async function instead.
const { promisify } = require('util')
const getLength = promisify(formData.getLength.bind(formData))
const contentLength = await getLength()
const headers = { 'content-length': contentLength, ...formData.getHeaders() }

Correct way to build FormData object to POST file in typescript? [duplicate]

From Angular I want to upload a image as Blob data to nodeJS server. The server uses multer in the backend. The image file is generated by canvas render. I am getting the following error from the server:
Error: Multipart: Boundary not found status:500
The following is my code. Please help me to find out the issue.
Angular:
// blob:Blob; -> it has valid image data.
var formData: FormData = new FormData();
formData.append('banner', blob, "my-file.png")
this.http.post(url,
formData, { headers: new Headers({ 'Content-Type': 'multipart/form-data' }) })
.toPromise()
.then(res => {
console.log(res);
return res.json();
})
.catch(this.handleError);
nodejs:
router.post('/upload-banner-image', bannerImageUpload.single('banner'), watchfaceController.uploadWatchfaceBannerImage);
Remove your 'Content-Type': 'multipart/form-data' header and it should work.
I got the same error, this is due to the missing boundary=.. just after multipart/form-data like the following working request:
When you remove your header, browsers will add it automatically with the boundary=.. and it works.
Add Content-Type': 'file' in header and it should work

Reactjs Nodejs file upload ftp via axios

I am trying to upload file using React Dropzone on ftp with Reactjs + AXIOS at front end, Nodejs + connect-multiparty at back end.
The problem is when I am sending file via front end using AXIOS, I am not getting the file at server in request.
My code to upload file using react-axios is
let data = new FormData()
data.append('file', file)
var setting = {
method: 'post',
url: 'my-server-url',
data:data,
headers: {
'Content-Type': 'multipart/form-data'
},
}
var response = axios(setting).then(response => { return response.data })
.catch(response => response = {
success: 500,
message: "Your submission could not be completed. Please Try Again!",
data: ""
});
while using postman, everything works fine. Server side api is working. only problem with client side request code.
Any help!!!
This is a very rookie mistake you're making probably because of the fact that you don't understand the way multipart works. For your client-side code to work, i.e form-data to be sent back to the backend, you need to:
Either remove the header and let the browser choose the header for you based on your data type
Or when using 'Content-Type': 'multipart/form-data', add a boundary to it
Multipart boundary looks like this,
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryABCDEFGHIJKLMNOPQRSTUVWXYZ'
Simply doing the following will solve the issue for you as the browser will take care of the headers needed.
axios.post('your-server-url', data).then(....)

Categories

Resources