send base64 string data to server but receive empty form value - google-app-engine

I have a front-end written in Vue and a backend written in Golang. I'm using Google app engine to run my backend service, and use gcloud datastore and gcloud storage to store the data and image that were submitted through front-end form.
I've been trying to upload an image using POST method. I convert the image to a base64 string. Then I add the data string to formdata and POST to my backend service. I keep getting empty form value in Go program. Is there a reason that Go cannot read base64 string, or I miss something important about FormData? Any help helps, thank you.
My front-end code:
var myForm = document.getElementById('myForm')
var formData = new FormData(myForm)
var imgBase64 = getBase64(//image-url//)
imgBase64.then(function (res) {
formData.append('image', res)
}
axios.post(' //go-app-engine-service// ', formData)
.then(res => {
console.log(res)
})
.catch(error => {
console.log(error)
})
function getBase64(url) {
return axios
.get(url, {
responseType: 'arraybuffer'
})
.then(response => Buffer.from(response.data, 'binary').toString('base64'))}
My Go code:
imgString := r.FormValue("image")
fmt.Printf("imgstring: %s, %d, %T\n", imgString, len(imgString), imgString) //=> getting empty imgString

Ok, after some research I realize the "scope" issue.
function getBase64 returns a Promise and have to handle the value inside the scope, so I move the axios.post in the Promise and I finally see the base64 value in Go program. Problem solved.
modified front-end code:
var myForm = document.getElementById('myForm')
var formData = new FormData(myForm)
var imgBase64 = getBase64(//image-url//)
imgBase64.then(function (res) {
formData.append('image', res)
axios.post(' //go-app-engine-service// ', formData)
.then(res => {
console.log(res)
})
.catch(error => {
console.log(error)
})
}

Related

Getting bad request from server (Spring boot) when using axios request

I'm currently stuck sending a request to my server and can not get a response. I have tried it on postman and it runs completely fine. However, when I try to put it on react, the back-end always response with a bad request.
Here is my code for the back-end
#GetMapping(value = "/searchPatient")
public ResponseEntity<?> searchPatients(#RequestParam String id_num,
#RequestParam String name) {
List<PatientForSearchDto> patientForSearchDtos = patientService.viewSearchedPatient(id_num, name);
return ResponseEntity.status(HttpStatus.OK).body(
new ResponseObject("ok", "Success", patientForSearchDtos)
);
}
Here is my code for Front end (react)
async function sendRequest () {
const formData = new FormData();
formData.append('id_num', id_num);
formData.append('name', name);
console.log(formData)
console.log(formData.get('name'))
console.log(formData.get('id_num'))
const config = {
method: 'get',
url: 'http://localhost:8080/api/searchPatient',
// headers : {
// 'Content-Type': 'from-data'
// },
data : formData
};
await axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
setPatientList(response.data.data.object)
})
.catch(function (error) {
console.log(error);
});
}
Here is what I get when sending request via postman
enter image description here
Here is when sending request using react
enter image description here
From the Axios docs about Request Config data param:
// data is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', 'DELETE , and
'PATCH'
So, data with GET method is not supported.
Can't you use params instead?

How to upload local video file to Google Cloud

I am stuck with a file upload process in a react app. In the app, I am trying to upload local video files to Google Cloud Storage.
I take the input file from:
<input type={`file`} accept=".mp4" onChange={VideoSelectChangeFunc} />
In VideoSelectChangeFunc, I get the local URL of the input file by,
let file = URL.createObjectURL(event.target.files[0])
Then I use it in axios to send to cloud
export const UploadVideo = async (file, signedurl, asset_uuid) => {
let resultState = { state: '', data: {} };
await axios({
method: 'put',
url: signedurl,
data: file,
headers: {
'Content-Type': 'application/octet-stream',
},
}).then(function (response) {
resultState.state = 'success';
resultState.data = response.data
}).catch(function (error) {
resultState.state = 'error';
resultState.data.message = error.message;
window.toastr.error(error.message);
console.log(error)
})
return resultState;
}
What I see on cloud is:
blob:http://localhost:3000/9b650cbf-8b49-440b-9e90-da6bdb5d392a
This is just the local URL of the file as string but not the video itself, when I copy and paste it on browser I can see the video. I searched the situation and saw 'Content-Type': 'blob' would solve the problem. However, we are checking headers in our CORS Policy, so it has to be 'Content-Type': 'application/octet-stream'. Is there a way to work this out?
Before sending it, converting the blob url into file worked. I have only added these two lines then, called axios.
let blob = await fetch(blobURL).then(r => r.blob());
var file = new File([blob], "thisVideo.mp4",{type:"video/mp4", lastModified:new Date().getTime()})
This can be useful, in the situations where the file is not uploaded right away but the url saved temporarily to be called later on which was the case here. If you are interested visit this question too:
How to get a file or blob from an object URL?

React Native File Upload not working using Axios

I am trying to upload a file to the server and the server APIs are written using django. The file upload is working perfectly from Postman but when i try to upload from mobile app (React Native) using axios the backend is not able to read it.
Following is the Frontend Snippet:
let accessToken = await AsyncStorage.getItem('accessToken')
let formData = new FormData()
formData.append('doc_type', this.state.selectedDoc.id)
formData.append('document', this.state.selectedFiles) // <- This is the fetched file in array format . [{filname:'abc', size:12344,.....}]
formData.append('description', this.state.description.value)
formData.append('data', JSON.stringify(this.state.selectedDoc.fields))
let url = `${AppConstants.url}api/${AppConstants.apiVersion}/upload_doc`
var config = {
method: 'post',
url: url,
data: formData,
headers: {
'Authorization': `Bearer ${accessToken}`,
}
}
axios(config)
.then((resp) => {
resolve(resp)
})
.catch((err) => {
reject(err)
});
And the backend-end if else statement is as follows:
if(request.FILES.getlist("document")):
files = request.FILES.getlist("document")
....
....
....
else:
return response.JsonResponse({
'success' : False,
'message' : 'Please Upload a file'
}, status = status.HTTP_200_OK)
The above else block is executed even though the UI is sending a valid file.
Request you to please share a solution.

Getting 401 from fetch in React - Passing sessionId

I'm building react app, first screen is a login form that is calling a GET rest api resource in other host (8080)(CORS extension on chrome was installed to overcome CORS issue).
After logging in successfully, trying to perform another GET fetch but this time am getting 401!
Tried setting the credentials: 'same-origin' or credentials: 'include' (in both calls, login and second one) but it didn't help!
fetch('http://<some host>:8080/WebServices/api/SessionManager/login?userName='
+ this.state.userName + '&password=' + this.state.password,
{
//credentials: "include",
//mode: "no-cors"
})
.then(
(response) => {
if (response.status < 200 || response.status > 300) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
this.state.showError = true;
this.state.errorMessage = 'Please enter a valid credentials.';
return;
} else {
localStorage.setItem('session', response);
console.log("Response ======>", response);
window.location.href = '/main';
}
}
)
.catch((error) => {
console.error(error);
});
second call:
function getSession(){
return localStorage.getItem('session').then(response => JSON.parse(response))
}
function getProjectDetails(){
let params = getSession();
let headers = new Headers();
fetch('http://<host>:8080/WebServices/api/ProjectManager/getProjectDetails?userSessionId=', params
// {
// //credentials: "include",
// //credentials: "same-origin",
// //crossdomain: true,
// //mode: 'no-cors',
// //headers: headers
// }
)
//.then(res => res.json())
.then((data) => {
this.setState({ projectsDetails: data })
console.log(data);
})
.catch(console.log);
}
class App extends Component {
Is there a way to get the session from browser cookies and set it into the header or parameters of fetch? how can I solve it?
If I understand it right you are asking how to store and retrieve stored values from the cookies.
First you need to store the data you get from the first fetch with, be aware that must convert he json response to string with JSON.stringify.
localStorage.setItem('session', JSON.stringify(response));
An then you can retrieve it with:
localStorage.getItem('session');
LocalStorage has to be stored as json, and decode it after getItem().
So in order to add the session params to the second fetch you can do as follows:
function getSession(){
return JSON.parse(localStorage.getItem('session'))
}
// second fetch,
function secondFetch(){
var params = getSession();
// in var params you have the data stored so now you can do the second fetch
}
I hope I've been of help to you, anything don't hesitate to ask.

PUT Request with AngularJS and Express

When I'm performing a put request and console.log(response) of the request I only get a JSON Object like {"res":1} instead of getting the whole json object with its changes in order to update him in a database.
Controller :
$scope.doneEdit = function (components) {
console.log(components);
components.editing = false;
if (components.editing === false) {
$http.put('/propt/' + components._id).then(function (response) {
console.log(response.data);
});
}
}
Express
app.put('/propt/:id', function(req,res) {
console.log(req.body);
testDb.update({_id:req.params.id}, req.body, {}, function(err, numReplaced){
res.statusCode = 200;
res.send(req.body);
})
})
You should pass the data you want to send as a second parameter to put method:
$http.put('/propt/' + components._id, {someValue:components.someValue})
You can find the documentation here: https://docs.angularjs.org/api/ng/service/$http#put

Resources