Can't send image to azure API - reactjs

I'm making OCR app using amazon. App I'm doing using react native. And I have an error on the moment when I send data.
Error:
{
"code": "InvalidImageUrl",
"requestId": "c495b0d7-a65a-4138-97a9-2b1cb25dced8",
"message": "Image URL is badly formatted."
}
Why? What am I doing wrong? Code:
// ...
selectImage() {
ImagePicker.showImagePicker(options, (response) => {
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
const source = { uri: response.uri };
this.setState({ imageSource: source });
this.extractText(response.uri);
}
});
}
extractText = async (imageSource) => {
// alert(imageSource)
let subscriptionKey = ['CODE'];
let endpoint = ['ENDPOINT']
if (!subscriptionKey) { throw new Error('Set your environment variables for your subscription key and endpoint.'); }
var uriBase = endpoint + "vision/v2.1/ocr";
// Request parameters.
// Display the image.
var sourceImageUrl = imageSource;
const data = new FormData();
data.append(imageSource);
fetch(uriBase + "?" + {
"language": "unk",
"detectOrientation": "true",
},
{
method: 'POST',
headers:
{
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': subscriptionKey,
},
body: '{"url": ' + '"' + data + '"}',
}).then((response) => response.json()).then((data) =>
{
console.log(JSON.stringify(data, null, 2));
}).catch((error) =>
{
console.log(error);
});
};
}
export default ImagePickerScreen;

Based on your code,there is something wrong with your data,it should an image URL so that Azure Version service can access it . I am not quite sure that how you get data in your custom logic . But anyway , this snippet below works , pls have a try :
const data = 'https://stanstroage.blob.core.windows.net/container2/personPic.jpg';
let subscriptionKey = '<key>';
let endpoint = '<endpoint>';
if (!subscriptionKey) { throw new Error('Set your environment variables for your subscription key and endpoint.'); }
var uriBase = endpoint + "vision/v2.1/ocr";
fetch(uriBase + "?" + {
"language": "unk",
"detectOrientation": "true",
},
{
method: 'POST',
headers:
{
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': subscriptionKey,
},
body: '{"url": ' + '"' + data + '"}',
}).then((response) => response.json()).then((data) =>
{
console.log(JSON.stringify(data, null, 2));
}).catch((error) =>
{
console.log(error);
});
Result:
If you want to upload a local image, you should use application/octet-stream as request content-type and set image content buffer as request body.
You can use react-native-fs to read your local image content and use buffer to get image content buffer and post it to Azure side , try snippet below below :
let subscriptionKey = '<key>';
let endpoint = '<endpoint>';
let fileUri = '<fileUri>';
let base64 = await fs.readFile(fileUri, 'base64');
let data = Buffer.from(base64, 'base64');
console.log(data);
if (!subscriptionKey) { throw new Error('Set your environment variables for your subscription key and endpoint.'); }
var uriBase = endpoint + "vision/v2.1/ocr";
fetch(uriBase + "?" + {
"language": "unk",
"detectOrientation": "true",
},
{
method: 'POST',
headers:
{
'Content-Type': 'application/octet-stream',
'Ocp-Apim-Subscription-Key': subscriptionKey,
},
body: data,
}).then((response) => response.json()).then((data) =>
{
console.log(JSON.stringify(data, null, 2));
}).catch((error) =>
{
console.log(error);
});
Result :

Related

react native base64 image upload fail with status code 400

I want to upload my image as base 64 to the server, after user pick image it stores as base64 in state and then I call upload function but it give me this error: request failed with status code 400.
I need to first call an API and it takes user id and respond with an upload name id, then I call upload image API
here is my implementation:
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
base64: true
});
setImage(result)
};
const uploadImagetoServer = async (userId) => {
let uploadId;
try {
const response = await axios
.post('URL', {
"id": userId
});
console.log('id res', response.data);
uploadId = response.data;
} catch (error) {
console.log(error.message);
}
try {
const response = await axios
.post('ANOTHER_URL', {
headers: {
'Content-Type': 'application/json'
},
"fileName": uploadId,
"fileBase64String": image.base64,
"folderName": "Users",
"fileExtension": ".jpg"
});
console.log('upload res', response.data);
} catch (error) {
console.log(error.message);
}
}
const allowAccess = async () => {
if (Platform.OS !== 'web') {
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') {
alert('Sorry, we need camera roll permissions to make this work!');
} else {
pickImage()
.then(() => {
uploadImagetoServer(userData.id)
})
}
}
}
anyone can help me with this? ty
you need to add contentType in headers
'Content-Type': `multipart/form-data;`,
here is an example
npm install --save form-data
import FormData from 'form-data'
let data = new FormData();
data.append('file', file, file.name);
return (dispatch) => {
axios.post(URL, data, {
headers: {
'accept': 'application/json',
'Accept-Language': 'en-US,en;q=0.8',
'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
}
})
.then((response) => {
//handle success
}).catch((error) => {
//handle error
});
};}

How to pass POST parameters in fetch for uploading image to server in React Native?

This is the code with I'm trying to send my image to server.
postData = async () => {
var location = await AsyncStorage.getItem('location');
var path = await AsyncStorage.getItem('path');
var post_type = await AsyncStorage.getItem('post_type');
var userId = await AsyncStorage.getItem('userID');
const formData = new FormData();
//I want to pass params in fetch but I don't know how to.
var params = JSON.stringify({
"user": userId,
"description": this.state.description,
"location": location,
"post_type": post_type,
});
const uriPart = path.split('.');
const fileExtension = uriPart[uriPart.length - 1];
formData.append('photo', {
uri: path,
name: `photo.${fileExtension}`,
type: `image/${fileExtension}`,
});
fetch(strings.baseUri+"addPosts",{
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
body: formData,
})
.then((response) => response.json())
.then((responseJson) => {
alert(responseJson); // This gives me error JSON Parse error: Unexpected EOF
})
.catch((error) => {
console.error(error);
});
}
I want to pass my parameters in fetch. The parameters are params in my case. I want to send these parameters along with my image to server. Please help.
UPDATE
this is when I used alert(JSON.stringify(response));
You can pass parameter with append
reference link: How do I post form data with fetch api?
const formData = new FormData();
formData.append('photo', {
uri: path,
name: `photo.${fileExtension}`,
type: `image/${fileExtension}`,
});
formData.append('user', userId);
formData.append('description', description);
formData.append('location', location);
formData.append('post_type', post_type);
FormData cannot take stringified JSON, but you can iterate over the object, appending values to the form.
Like this:
var params = {
"user": userId,
"description": this.state.description,
"location": location,
"post_type": post_type,
};
const uriPart = path.split('.');
const fileExtension = uriPart[uriPart.length - 1];
formData.append('photo', {
uri: path,
name: `photo.${fileExtension}`,
type: `image/${fileExtension}`,
});
Object.keys(params).forEach(key => formData.append(key, params[key]));
fetch(strings.baseUri+"addPosts",{
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
body: formData,
})
.then((response) => response.json())
.then((responseJson) => {
alert(responseJson); // This gives me error JSON Parse error: Unexpected EOF
})
.catch((error) => {
console.error(error);
});
}

React-Native image upload

Is it possible to upload file (images) to server with react-native using FormData? Tried to use it like this:
var data = new FormData();
data.append('file', file);
console.log(JSON.stringify(data));
var id = 5;
fetch('http://192.168.1.104:3000/app/complaint/uploadFile?id='+id,{
method:'POST',
body: data,
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data;',
},
});
For React, FormData works as expected but for React-Native not working.
I have also tried (used in react - working)
const data = fetch('http://192.168.1.104:3000/app/complaint/uploadFile?id='+id, {
credentials: "same-origin",
method:'POST',
body: dataval,
timeout: 1000000000,
});
But nothing works,
In the back-end server, I am upload using
var d = require('domain').create()
d.run(function safelyUpload () {
var file=req.file('file').upload({dirname: path.resolve(sails.config.appPath, folder),
}, function whenDone(err, uploadedFiles) {
if (err) return res.serverError(err);
else{
sails.log.debug('Complaint File data : ' +util.inspect(uploadedFiles, {showHidden: true,depth: null}));
}
});
});
Is there any other ways
Here is example to upload image using Fetch API
const photo = {
uri: user.profilePicture,
type: 'image/jpeg',
name: 'photo.jpg',
};
const form = new FormData();
form.append("ProfilePicture", photo);
fetch(
URL,
{
body: form,
method: "PUT",
headers: {
'Content-Type': 'multipart/form-data',
'Authorization': 'Bearer ' + user.token
}
}
).then((response) => response.json())
.catch((error) => {
alert("ERROR " + error)
})
.then((responseData) => {
alert("Succes "+ responseData)
}).done();
Credits https://stackoverflow.com/a/36649457/5315786

Return data from method in object

I have been trying to figure this one out and I'm not getting how to return the data to another method and call it so that I don't have to statically add the data into my request. I keep getting undefined data on my B2C method when I run it for the data returned from this.O_Auth. Any clues?
let obj = {
O_Auth(key, secret) {
const key = Key;
const secret = Secret;
const auth = "Basic " + new Buffer(key + ":" + secret).toString("base64");
request(
{
uri: "https://randomurl",
method: 'GET',
headers: {
"Authorization": auth
}
},
(err, res, body) => {
if (err) {
return err;
} else {
// console.log(body);
let response = JSON.parse(body);
let res = JSON.stringify(response.access_token)
return res;
}
}
);
},
B2C(params) {
console.log("Random " + this.O_Auth('first', 'second'));
let options = {
method: 'POST',
uri: 'https://randomurl',
headers: {
"Authorization": "Bearer " + this.O_Auth('first', 'second'),
"Content-Type": "application/json"
},
body: {
//values
},
json: true
};
rp(options)
.then(function (body) {
console.log(body);
})
.catch(function (err) {
console.log(err);
});
}
}
Ended up figuring out the asynchronous nature of JavaScript meant I was requesting data that was being evaluated later so I used a promise to get the data and output it first before using it in a subsequent promise that outputs the body. Changed the first request to request promise (rp) that returns the options that will be needed for that promise in the second method.
let obj = {
O_Auth(Key, Secret) {
const key = Key;
const secret = Secret;
const auth = "Basic " + new Buffer(key + ":" + secret).toString("base64");
let options = {
uri: "https://randomurl",
headers: {
"Authorization": auth
},
json: true
};
return rp(options)
},
B2C(param1, param2, param3...) {
this.O_Auth('first', 'second'))then(response =>{
let token = response.access_token;
let options = {
method: 'POST',
uri: 'https://randomurl',
headers: {
"Authorization": "Bearer " + token,
"Content-Type": "application/json"
},
body: {
//values
},
json: true
};
rp(options)
.then(function (body) {
console.log(body);
})
.catch(function (err) {
console.log(err);
});
}).catch(error => console.log(error));
}
}

angular2 webapi call async not working

I have an angular 2app with a class and a method, the method executes a web api call and then sets some items on local storage, the problem is that because its ASYNC then on the next line I dont have the local storage values yet because the web api hasnt returned any info at that point.
How can I make sure that the web api has been succesfully returned before the localstorage.getitem line.
Code reduced for brevity.
Service
login(email) {
let params: URLSearchParams = new URLSearchParams();
params.set('email', email);
//Header
let headers = new Headers({
'Content-Type': AppSettings.ContentType,
'Authorization': AppSettings.Authorization + localStorage.getItem("AccessToken"),
'X-Developer-Id': AppSettings.XDeveloperId,
'X-Api-Key': AppSettings.XApiKey
});
var RequestOptions: RequestOptionsArgs = {
url: AppSettings.UrlLoginPatient,
method: 'GET',
search: params,
headers: headers,
body: null
};
this.http.get(AppSettings.UrlLoginPatient, RequestOptions)
.map(res => res.json())
.subscribe(
data => { this.saveData(data, email); },
err => this.Error(err)
);
}
saveData(data, email) {
localStorage.setItem('patientId', data.data.patientId);
localStorage.setItem('emailLogin', email);
}
Error(err) {
console.log('error: ' + err);
}
Component
LoginApp() {
this.login.login('a#com.com');
if (localStorage.getItem("patientId") != null) {
this.navCtrl.push(AttentionTypePage);
} else {
let alert = this.alertCtrl.create({
subTitle: 'El correo electrónico no ha sido encontrado.',
buttons: ['Intentar nuevamente']
});
alert.present();
}
}
To ensure that you have the right informations, you shouldn't subscribe in your service but in your component :
Service
login(email) {
//do stuff with headers, and request options
return this.http.get(AppSettings.UrlLoginPatient, RequestOptions)
.map(res => res.json())
.do(data => this.saveData(data, email));
}
Component
LoginApp() {
this.login.login('a#com.com').do(data => {
if (localStorage.getItem("patientId") != null) {
this.navCtrl.push(AttentionTypePage);
} else {
let alert = this.alertCtrl.create({
subTitle: 'El correo electrónico no ha sido encontrado.',
buttons: ['Intentar nuevamente']
});
alert.present();
}
}).subscribe();
}

Resources