I'm trying to send an image from an android device to a laravel api using react native, but it doesn't read the url of the image, i.e Unable to init from given url (file:///storage/emulated/0/DCIM/Camera/IMG_20181013_133327.jpg, it always brings that error, it doesn't read the url of the image, file:///storage/emulated/0/DCIM/Camera/IMG_20181013_133327.jpg please how can I send the image to my laravel api successfully or I can I download based on the location of the image on the android device
REACT NATIVE AXIOS
//THE IMAGES ARE FIRST SELECTED AND THE IMAGES ARRAY IS SET WITH THE URI OF THE IMAGES
imageUpload(){
ImagePicker.openPicker({
multiple: true,
cropping: true,
mediaType: 'photo'
}) .then(images => {
console.log(images);
const imagesArray = [];
if(images){
images.map(i => {
imagesArray.push({uri: i.path, type: i.mime, name: i.path});
} );
}
this.setState({
images_array: imagesArray
});
console.log(imagesArray);
console.log(this.state.images_array);
}).catch(e => console.log(e));
}
//THE IMAGES ALONG WITH OTHER DETAILS ARE SENT TO THE LARAVEL API
seller(){
this.setState({loader: true});
var data = {
name: this.state.name,
// user_id: this.state.user_id,
user_id: 18,
description: this.state.description,
amount: this.state.amountT,
qty: this.state.qty,
cat_id: this.state.cat_id,
photos: this.state.images_array
};
/* var config = {
headers: {'Authorization': "Bearer " + this.state.token}
};*/
axios.post(
'http://10.0.2.2:8000/api/sell',
data,
// config
).then((response) => {
this.setState({loader: false});
console.log(response);
Alert.alert(
'Success',
'Product posted Successfully',
[
{text: 'OK', onPress: this.props.navigation.navigate('Land', {})},
], );
}).catch((error) => {
this.setState({loader: false});
Alert.alert(
'Error',
'Internal Server Error, please try again later',
[
{text: 'OK'},
], );
console.log(error);
});
};
LARAVEL BACKEND, i.e Intervention Image api is used
public function imagesUpload($goodsId, $photos){
$images = $photos;
// $count = $images->count;
foreach($images as $image){
$uri = $image['uri'];
$filename = basename($uri);
Image::make($uri)->save(public_path('img/' . $filename));
$saver = new Images;
$saver->product_id = $goodsId;
$saver->location_url = 'img/'.$filename;
$saver->save();
}
return true;
}
using double // does not work on real devices , it may work on emulator but not on real devices .
try using this
uri:'file:///storage/emulated/0/DCIM/IMG_20161201_125218.jpg'
make sure to use /// three forward slashes.
Related
I am using MediaCapture library but getting 403. Below is my code:
MediaCapture.captureImage(options).then(
async (data: any) => {
const contents: any = await Filesystem.readFile({
path: data[0].fullPath,
});
setPreviewImage(contents);
let blobData: any = {};
let formdata = new FormData();
formdata.append(
"file",
`data:${data[0].type};base64,${contents.data}`
);
const response = (await axios.post(
Endpoints.userCover,
formdata
)) as ServerResponse;
if (response.status) {
console.log(response);
console.log("-------------------- IMAGE Camera");
}
},
(err) => console.error(err, " error")
);
enter image description here
Getting 403 on MediaCapture library when using Camera but it's working when selecting image from the android Gallery.
I got very strange issue: we have scan functionality for documents in our app and as the result scan give's me encoded base64 image with photo. Everything is good on ios platform but when I trying to send my picture on android, I get xhr.status 0 and error. Also, next strange thing is that when I starting debug mode and enable network inspection in react-native-debugger, picture is sending without errors. I was trying it on release app version, installed on my device, but still got an error with status 0
XHR request
export const uploadXHRImage = (url: string, data: IDataUploadImage) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve('Image successfully uploaded to S3');
} else {
reject(localize('failedUploadImage'));
}
}
};
xhr.ontimeout = () => reject(localize('timeoutUploadImage'));
xhr.timeout = UPLOAD_IMAGE_TIMEOUT;
xhr.open('PUT', url);
xhr.setRequestHeader('Content-Type', data.type);
xhr.send(data);
});
};
Add to header:
"Content-Type": 'application/json',
"Connection": "close",
I found the answer: Android can not process xhr send image, while image isn't saved as file in cache or other directory. Also, android needs file:// before data. Example is here:
saveImage = (image: string) => {
if (IS_IOS) {
return `data:image/jpg;base64,${image}`;
}
const tempFileDirectory = `${fs.CachesDirectoryPath}`;
const tempFilePath = `${tempFileDirectory}/${uuidv4()}.jpg`;
fs.writeFile(tempFilePath, image, 'base64');
return `file://${tempFilePath}`;
};
I am trying to create an excel sheet from React Native mobile application. I have tried using xlsx to generate excel. But it is not supporting the styling excel sheet. Is it possible to use ExcelJS in React Native?
Yes, it is possible with the help of Google spreadsheet and tabletop library. After searching a lot I found this way:
Install the tabletop library.
Upload your .xlsx file in google drive.
Now in select File -> Share-> Publish to web.
Once you click a new window open and your file published.
Now close this window and copy the key of your file.
The Key will be found in the URL of the browser.
Forex:
https://docs.google.com/spreadsheets/d/108O2Memo7yJ3-7fzngFSoulVj-J32vwcyLDu5Lslhik/edit#gid=1371815480
In the above URL: this will be the key "108O2Memo7yJ3-7fzngFSoulVj-J32vwcyLDu5Lslhik"
6. Now in your code pass this key to the init method of the tabletop.
7. Get data from the file and show it in the list.
Library install :
npm install tabletop
In component did mount I initialize tabletop.
componentDidMount() {
// Facts
Tabletop.init({
key: 'keyCopyFromUrl',
callback: googleData => {
this.setState({
arrayFacts: googleData
})
},
simpleSheet: true
});
Now for showing this data
<FlatList
data={this.state.arrayFacts}
renderItem={this.renderItemFacts}
keyExtractor={(key, index) => index.toString()}
/>
First of all install the required modules (assuming usage of Expo):
npm install --save exceljs
expo install expo-file-system
expo install expo-sharing
Code example - Imports:
// Required to save to cache
import * as FileSystem from 'expo-file-system';
// ExcelJS
import ExcelJS from 'exceljs';
// From #types/node/buffer
import { Buffer as NodeBuffer } from 'buffer';
// Share excel via share dialog
import * as Sharing from 'expo-sharing';
Code example - Function to generate Excel and return uri
// This returns a local uri that can be shared
const generateShareableExcel = async (): Promise<string> => {
const now = new Date();
const fileName = 'YourFilename.xlsx';
const fileUri = FileSystem.cacheDirectory + fileName;
return new Promise<string>((resolve, reject) => {
const workbook = new ExcelJS.Workbook();
workbook.creator = 'Me';
workbook.created = now;
workbook.modified = now;
// Add a sheet to work on
const worksheet = workbook.addWorksheet('My Sheet', {});
// Just some columns as used on ExcelJS Readme
worksheet.columns = [
{ header: 'Id', key: 'id', width: 10 },
{ header: 'Name', key: 'name', width: 32 },
{ header: 'D.O.B.', key: 'dob', width: 10, }
];
// Add some test data
worksheet.addRow({ id: 1, name: 'John Doe', dob: new Date(1970, 1, 1) });
worksheet.addRow({ id: 2, name: 'Jane Doe', dob: new Date(1969, 2, 3) });
// Test styling - what OP wanted
worksheet.eachRow((row, rowNumber) => {
row.getCell(1).font = {
name: 'Arial Black',
color: { argb: 'FF00FF00' },
family: 2,
size: 14,
bold: true
};
});
// Write to file
workbook.xlsx.writeBuffer().then((buffer: ExcelJS.Buffer) => {
// Do this to use base64 encoding
const nodeBuffer = NodeBuffer.from(buffer);
const bufferStr = nodeBuffer.toString('base64');
FileSystem.writeAsStringAsync(fileUri, bufferStr, {
encoding: FileSystem.EncodingType.Base64
}).then(() => {
resolve(fileUri);
});
});
});
}
Code Example - Function to share generated Excel. Call this, for example, on the press of a button:
const shareExcel = async () => {
const shareableExcelUri: string = await generateShareableExcel();
Sharing.shareAsync(shareableExcelUri, {
mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // Android
dialogTitle: 'Your dialog title here', // Android and Web
UTI: 'com.microsoft.excel.xlsx' // iOS
}).catch(error => {
console.error('Error', error);
}).then(() => {
console.log('Return from sharing dialog');
});
}
I'm trying to send/upload image file to my back-end serve using fetch multipart upload in react-native, but fetch multipart form data upload is not working for android, however I tried different examples.
Image upload multipart form data API is based on php and its working for iOS react-native app.
I am using react-native-photo-upload library for taking image.
storePicture(PicturePath:string) {
console.warn(PicturePath);
if (PicturePath) {
const apiUrl = `${Constants.APIHOST}updateprofileimage.php`;
// Create the form data object
var data = new FormData();
data.append('profileimage', { uri:PicturePath, name: 'profileimage.jpg', type: 'image/jpg/jpeg' });
data.append('accesstoken', this.state.user.sAccessToken);
data.append('react-native', 1);
// Create the config object for the POST // You typically have an OAuth2 token that you use for authentication
const config = { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'multipart/form-data;' }, body: data };
fetch(apiUrl, config)
.then(responseData => { // Log the response form the server
// Here we get what we sent to Postman back
console.warn(`response:${responseData}`);
})
.catch(err => {
console.warn(err);
});
}}
Here is the example how I am calling storePicture() function.
<PhotoUpload onResizedImageUri={
avatar => {
if (avatar) {
this.storePicture(avatar.path);
}
}}
>
<Image source={{uri: this.state.user.sProfileImageUrl}} style={{resizeMode:"cover", marginTop:8.0, backgroundColor:'transparent', height:120.0, width:120, borderRadius:60.0, borderWidth:0.0, borderColor:'transparent'}}/>
</PhotoUpload>
uploadProfileImage = async (image:var) => {
this.setState({
loading: true
});
var RNFS = require('react-native-fs');
const path = Style.IS_IOS ? image.uri : image.path;
var fileName = path.split('/').pop();
var fileType = fileName.split('.').pop();
var filePath = Style.IS_IOS ? path : 'file://' + path;
const apiURL = `${Constants.APIHOST}updateprofileimage.php`;
const formData = new FormData();
formData.append('accesstoken', this.state.user.sAccessToken);
formData.append('reactnative', 1);
formData.append('profileimage', {
uri:filePath,
name: fileName,
type: `image/${fileType}`,
});
try {
const response = await fetch(apiURL, {
body: formData,
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
},
})
const json = await response.json()
this.handleUploadImageResponse(json);
} catch (err) {
this.setState({
loading: false
},console.log('catch Error: '+ err));
}
}
I am answering my own question as I haven't found any valid answer for the sake of other users, who are facing same issue.
Please let me know if I can improve my answer/post or in case any help is needed from me.
Image Upload to an API by Multipart FormData
uploadPicture = () => {
console.log(
"Image Upload urI = " + JSON.stringify(this.state.imageSourceUri.uri)
);
this.setState({ loading: true });
const form = new FormData();
form.append("fileToUpload", {
uri: this.state.imageSourceUri.uri,
type: "image/jpg",
name: "12334"
});
fetch("http://119.82.97.221/HPBSProjectApi2/api/HPBS/PostFormData", {
method: "post",
body: form
})
.then(response => response.json())
.then(response => {
console.log("response = " + response);
this.setState({
loading: false
});
});
};
the problem is the type field in the FormData, use mime to resolve it. Images must be image/jpeg.
const formData = new FormData();
formData.append("image",{..., name, uri, type: mime.getType(uri)}));
I'm having an ugly issue that only affect my expo app on Android.
Im trying to upload a base64 image taken with expo ImagePicker to Firebase Storage passing the image value with a http-request made with axios to a Firebase Cloud Function which returns the url of the saved image. This url goes in Firestore, but this is out of reach of my question I think.
My current implementation works flawless in IOS (I can get as many urls as I want, they upload pretty quick actually) but, in Android I only can upload 2 images in a row; when I try for the third time, my app get frozen when reach axios/fetch* statement and gives no clue of whats happened. Console is just as it was before trying the third time and the apps or simulators freeze.
Here you can see this behaviour in a 2 min video:
https://youtu.be/w66iXnKDmdo
When I begun working in this bug I was using fetch instead of axios. At that time the issue was that I was able to upload only one image. It were necessary to close and open the app again to upload one more. Now with axios Im able to upload 2 insted of one, but the problem persist.
This is how I implemented the code:
const imageBase64 = 'QWEpqw0293k01...'
This is how I upload the image to Firebase Cloud Storage:
export const savePhoto = (imageBase64) => {
const db = firebase.firestore();
const docRef = db.collection('Comidas').doc();
return () => {
uploadImageToFirestore(imageBase64)
.then(imageUrl => {
console.log('image-url: ', imageUrl);
docRef.set({ imagen: { uri: imageUrl }, });
})
.catch(err => console.log('error: ', err));
};
};
I made a function helper that allow me to make the http request reusable:
import axios from 'axios';
export const uploadImageToFirestore = (imageBase64) => {
//<--- here is where it get frozen the third time
//<--- console.log() calls three times but not axios
return axios({
method: 'post',
url: 'https://us-central1-menuapp-9feb4.cloudfunctions.net/almacenamientoImagen',
data: {
image: base64
},
})
.then(res => res.data.imageUrl)
.catch(err => console.log('error while uploading base64: ', err));
};
This invoques the following Firebase Cloud Function:
exports = module.exports = functions.https.onRequest((req, res) => {
cors(req, res, () => {
const body = req.body;
console.log('image: ', body.image);
fs.writeFileSync("/tmp/uploaded-image.jpg", body.image, "base64", err => {
console.log(err);
return res.status(500).json({ error: err });
});
const bucket = gcs.bucket("myapp.appspot.com");
const uuid = UUID();
bucket.upload(
"/tmp/uploaded-image.jpg",
{
uploadType: "media",
destination: "/comidas/" + uuid + ".jpg",
metadata: {
metadata: {
contentType: "image/jpeg",
firebaseStorageDownloadTokens: uuid
}
}
},
(err, file) => {
if (!err) {
console.log('url: ', {
imageUrl:
"https://firebasestorage.googleapis.com/v0/b/" +
bucket.name +
"/o/" +
encodeURIComponent(file.name) +
"?alt=media&token=" +
uuid
});
res.status(201).json({
imageUrl:
"https://firebasestorage.googleapis.com/v0/b/" +
bucket.name +
"/o/" +
encodeURIComponent(file.name) +
"?alt=media&token=" +
uuid
});
} else {
console.log(err);
res.status(500).json({ error: err });
}
}
);
});
});
I know that axios it’s not being called because there is no log neither register of the Firebase Cloud Function execution.
I expect this code to upload as many images as user consider he/she needs, not just 2 per app session as it does at this moment
How can I solve this?