I am trying to upload an image from my image gallery into my firebase storage folder with ionic. This works fine for ios emulator but does not work on android. What might be the problem ? What should I check ?
// this is the default options
$scope.capturarFoto = function (type) {
var opcionesCaptura = {
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType[type.toUpperCase()],
};
$cordovaCamera.getPicture(opcionesCaptura)
.then(procesarImagen, procesarError);
};
function procesarImagen(pathImagen) {
var directorioFuente = pathImagen.substring(0, pathImagen.lastIndexOf('/') + 1),
archivoFuente = pathImagen.substring(pathImagen.lastIndexOf('/') + 1, pathImagen.length),
nombreParaGuardar = new Date().valueOf() + archivoFuente;
$cordovaFile.readAsArrayBuffer(directorioFuente, archivoFuente)
.then(function (success) {
var blob = new Blob([success], {type: 'image/jpeg'});
enviarFirebase(blob, nombreParaGuardar);
}, function (error) {
console.error(error);
});
}
function enviarFirebase(file, nombre) {
var storageRef = firebase.storage().ref();
var uploadTask = storageRef.child('images/' + nombre).put(file);
uploadTask.on('state_changed', function (snapshot) {
console.info(snapshot);
}, function (error) {
console.error(error);
}, function () {
var downloadURL = uploadTask.snapshot.downloadURL;
console.log(downloadURL);
I am also new to Cordova but I believe for Camera functionality you would need to ensure that your device is ready:
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(navigator.camera);
/* Here you can have $scope.choosePhoto = ... */
}
I'm sure this is the approach you'd have to take. Try that and see if it works.
Ionic 4 + Firestore(Save Meta info) + Firebase Storage(Store real files)
Tutorial link
Related
I have an component that displays and image either taken by camera or selected from gallery. The point is when a user clicks the upload button i should send that Image to my server, but i am having difficulties extracting the file from the Image component.
<Image ref="profileImage" borderRadius="100" width="150" height="150" marginTop="20" stretch="aspectFill" :src="profileImage" />
And i have two functions for picking an image or capturing one
capture: function() {
var isAvailable = camera.isAvailable();
if (isAvailable) {
var options = {
width: 300,
height: 300,
keepAspectRatio: false,
saveToGallery: false,
cameraFacing: 'front'
};
var self = this;
var imageModule = require("tns-core-modules/ui/image");
camera.requestPermissions().then(
function success() {
camera.takePicture(options)
.then(function(imageAsset) {
self.profileImage = imageAsset;
}).catch(function(err) {
console.log("Error -> " + err.message);
});
},
function failure() {
// permission request rejected
}
);
}
},
pick() {
var self = this;
let context = imagepicker.create({
mode: 'single',
mediaType: 'image'
});
context.authorize()
.then(function() {
return context.present();
})
.then(selection => {
selection.forEach(selected => {
self.profileImage = selected;
});
}).catch(function(e) {
console.log('error in selectPicture', e);
});
},
What i need to do next is get the uploaded image and send it to server but i can't seem to find an options for that, i have the src of the and that's it in this case...
You can simply get ImageSource from ImageAsset and write it as file in data or temp directory, then upload it to server.
const imageSourceModule = require("tns-core-modules/image-source");
const fileSystemModule = require("tns-core-modules/file-system");
function uploadAsset(asset) {
imageSourceModule.fromAsset(asset)
.then(function(imageSource) {
var folderDest = fileSystemModule.knownFolders.documents();
var pathDest = fileSystemModule.path.join(folderDest.path, "test.png");
var saved = imageSource.saveToFile(pathDest, "png");
if (saved) {
console.log("Image saved successfully!");
// Now file is written at path `pathDest`
}
}).catch(function(err) {
console.log(err);
});
}
....
uploadAsset(profileImage);
Learn more at docs
I am facing a very strange issue that my Image size increases while uploading to firebase.
I have logged the file size before uploading, it is showing the same size but after uploading the file size gets increased. Also the image is not corrupted. Please help..
Uploading to firebase code :
async uploadImageAsync(uri, passedParameter, ItemName) {
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function() {
resolve(xhr.response);
};
xhr.onerror = function(e) {
console.log(e);
reject(new TypeError("Network request failed"));
};
xhr.responseType = "blob";
xhr.open("GET", uri, true);
xhr.send(null);
});
const ref = firebase
.storage()
.ref()
.child("CategoryDescription" + "/" + passedParameter + "/" + ItemName);
const snapshot = await ref.put(blob);
blob.close();
const downloadUrl = await snapshot.ref.getDownloadURL();
return downloadUrl;
}
**Pick Image code : **
async _pickImage() {
const { CAMERA, CAMERA_ROLL } = Permissions;
const permissions = {
[CAMERA]: await Permissions.askAsync(CAMERA),
[CAMERA_ROLL]: await Permissions.askAsync(CAMERA_ROLL)
};
if (
permissions[CAMERA].status === "granted" &&
permissions[CAMERA_ROLL].status === "granted"
) {
var pickerResult = await ImagePicker.launchImageLibraryAsync({
quality: 0.1
});
if (!pickerResult.cancelled) {
console.log(pickerResult);
this.setState({
itemImage: pickerResult.uri
});
** On button pressed code**
handleConfirmAddItems = () => {
var passedParameter = this.params.item.key;
const { ItemName, ItemPrice, ItemDesc, ItemWeight, itemImage } = this.state;
{
itemImage !== "" &&
this._handleImagePicked(itemImage, passedParameter, ItemName);
}
writeUrlToDB(
itemImage,
passedParameter,
ItemName,
ItemDesc,
ItemPrice,
ItemWeight
);
}
};
** handle image picked **
async _handleImagePicked(itemImage, passedParameter, ItemName) {
try {
const uploadUrl = await this.uploadImageAsync(
itemImage,
passedParameter,
ItemName
);
this.setState({ itemImage: uploadUrl });
console.log("itemIma", uploadUrl);
} catch (e) {
console.log(e);
alert("Upload failed, sorry :(");
}
}
Please help.. I am in great stress
A bug in Image picker.. This is the issue in the case of iOS Simulator, in Android device its working fine : )
I'm new to NativeScript and I'm trying to capture an image with the camera module (this works fine), and convert it to base64 (this is not working) and POST to server.
I've googled for days. Any help you can lend would be immensely appreciated.
I've tried this about 16 billion different ways and this is my current code:
viewModel.takePicture1 = function() {
camera.requestPermissions();
var isAvailable = camera.isAvailable();
console.log(isAvailable);
var options = { width: 640, keepAspectRatio: true, saveToGallery: false };
camera.takePicture().then(function (img) {
try{
var imageData = img.toBase64String("jpeg"); // fails here
console.log(imageData);
}catch(err){
console.log("Error: "+err);
}
http.request({
url: "http://[server address]/lab/ns_exp/upload_test.php",
method: "POST",
headers: { "Content-Type": "application/base64" },
content: imageData
}).then(function() {
console.log("Upload successful");
}).catch(function(e) {
console.log("Unsuccessful upload", e);
});
});
}//
Oh, I do want to make clear that I'm not using angular (obviously), so please don't provide an answer that does so. : ) (Vuejs Holdout)
The key here is that base64 needs to know that the image is a JPEG, and what quality the image should be. The code should look like this:
camera.takePicture(cameraOptions)
.then(imageAsset => {
imageSource.fromAsset(imageAsset).then(res => {
myImageSource = res;
var base64 = myImageSource.toBase64String("jpeg", 100);
Just in case someone finds this later and wonders about putting the image (UI) and/or the image (base64) into an observableArray, here is my complete function:
viewModel.takePhoto = function(){
var self = this;
camera.requestPermissions();
var cameraOptions = { width: 640, keepAspectRatio: true, saveToGallery: false };
camera.takePicture(cameraOptions)
.then(imageAsset => {
imageSource.fromAsset(imageAsset).then(res => {
myImageSource = res;
var base64 = myImageSource.toBase64String("jpeg", 100);
self.photoData.push({"data": base64});
var image = new imageModule.Image();
image.src = imageAsset;
self.photoUI.push({"src": image.src});
listView.refresh();
})
}).catch(function (err) {
console.log("Error -> " + err.message);
});
}
I am trying to select a picture from the user's gallery, view it in an ImageView and then save it for upload.
I am using the nativescript-imagepicker plugin.
Here is how i select the image from gallery and set it on the ImageView :
export function selectPicture() :void{
let context = imagePicker.create({
mode : "single"
});
context.authorize()
.then(()=>{ return context.present();})
.then((selection)=>{
selection.forEach((selected)=>{
selected.getImage().then((value :ImageSource)=>{
imageView.imageSource = value;
})
})
});
}
An this is how I save it and upload it :
export function upload():void{
try {
let photoPath = FileNameService.generatePictureFilePath();
let fileName = FileNameService.getFilenameFromPath(photoPath);
//this is where I get the error
**fromAsset(imageView.src)**.then(
(res) => {
imageSource = res;
let saved = imageSource.saveToFile(...);
if(saved){//doStuff },
(error)=>{
alert("Error " + error);
})
}catch (e){
alert(e);
}
}
the fromAsset function is throwing the following error :
asset.getImageAsync is not a function
What am I doing wrong?
When you get the selected item from the gallery you could use ImageSource saveToFile(<path>, <file_format>); method to save the image. Then you will be able the use the file path to upload the image to the needed backend service. You could review the below-attached example.
function startSelection(context) {
context
.authorize()
.then(function() {
imageItems.length = 0;
return context.present();
})
.then(function(selection) {
selection.forEach(function(selected_item) {
selected_item.getImage().then(function(imagesource){
let folder = fs.knownFolders.documents();
let path = fs.path.join(folder.path, "Test"+counter+".png");
let saved = imagesource.saveToFile(path, "png");
if(saved){
var task = sendImages("Image"+counter+".png", path);
var item = new observable.Observable();
item.set("thumb", imagesource);
item.set("uri", "Test"+counter+".png");
item.set("uploadTask", task);
imageItems.push(item);
}
counter++;
})
});
}).catch(function (e) {
console.log(e);
});
}
For further help, you could also review the sample project here.
I'm making a hybrid app with AngularJS and Cordova, using a Laravel 4 API & Backoffice.
I can make a picture with the application, but it does not upload. I don't really know how to upload the picture, and i don't really know how i can troubleshoot all of it.
I upload the image to the API-route i wrote, using the same upload-method as i use to do with the backoffice. This is what i have in the AngularJS-Controller, which uses Cordova to do the stuff.
var pictureSource; // picture source
var destinationType; // sets the format of returned value
pictureSource = navigator.camera.PictureSourceType;
destinationType = navigator.camera.DestinationType;
function clearCache() {
navigator.camera.cleanup();
}
var retries = 0;
function onPhotoDataSuccess(fileURI) {
var win = function (r) {
clearCache();
retries = 0;
alert('Done!');
}
var fail = function (error) {
if (retries == 0) {
retries ++
setTimeout(function() {
onPhotoDataSuccess(fileURI)
alert("kgoa ne keer opnief beginne");
}, 1000)
} else {
retries = 0;
clearCache();
alert('Ups. Something wrong happens!');
}
}
var options = new FileUploadOptions();
options.fileKey = "image";
options.fileName = fileURI.substr(fileURI.lastIndexOf('/') + 1);
options.mimeType = "image/jpeg";
options.params = {};
params.value1 = "test";
params.value2 = "param";
// if we need to send parameters to the server request
var ft = new FileTransfer();
ft.upload(fileURI, encodeURI("http://10.0.1.13/ClimbrBackoffice/public/api/routes/new/create"), win, fail, options);
}
// Called when a photo is successfully retrieved
//
function onPhotoURISuccess(imageURI) {
// Uncomment to view the image file URI
// console.log(imageURI);
// Get image handle
//
var largeImage = document.getElementById('largeImage');
// Unhide image elements
//
largeImage.style.display = 'block';
// Show the captured photo
// The inline CSS rules are used to resize the image
//
largeImage.src = imageURI;
}
// A button will call this function
//
$scope.capturePhoto = function(){
// Take picture using device camera and retrieve image as base64-encoded string
navigator.camera.getPicture(onPhotoDataSuccess, onFail, {
quality : 100,
destinationType : Camera.DestinationType.FILE_URI,
sourceType : Camera.PictureSourceType.CAMERA,
allowEdit : true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 250,
targetHeight: 400,
saveToPhotoAlbum: true,
correctOrientation: true
});
}
// A button will call this function
//
$scope.getPhoto = function(source) {
// Retrieve image file location from specified source
navigator.camera.getPicture(onPhotoURISuccess, onFail, { quality: 100,
destinationType: destinationType.FILE_URI,
sourceType: source });
}
I searched the web for good tutorials or explanations, but they drove me crazy.
Can someone please help me out?
Thanks!
Thomas
Your Angular controller should have the following function
$scope.upload = function() {
var options = {
fileKey: "file",
fileName: "image.png",
chunkedMode: false,
mimeType: "image/png"
};
$cordovaFileTransfer.upload("http://yourdomain.com/image_handler", "/android_asset/www/img/ionic.png", options).then(function(result) {
console.log("SUCCESS: " + JSON.stringify(result.response));
$scope.showAlert('Done', 'File Uploaded');
}, function(err) {
console.log("ERROR: " + JSON.stringify(err));
$scope.showAlert('Error', err);
}, function (progress) {
// constant progress updates
});}
And on your server, Laravel function could simply handle the image as:
public function getImageFromDevice(){
$destinationPath = 'uploads/';
$newImageName='MyImage.jpg';
Input::file('file')->move($destinationPath,$newImageName);
}
Do not forget to inject $cordovaFileTransfer in your controller.
That's it, this is a simple example you can extend it.
Credits to: Phonegap + Laravel 4 How to upload file