cordova camera plugin issue with FILE_URI - ionic-framework

I am using IONIC 3.7.0 in my current project. In one requirement I need to use cordova camera plugin to take photo uri from image gallery. Every time when I am trying to get the URI , I get the data_uri which is base64 long string.
I only need the file_uri of image to go further. Please suggest.
var options = {
sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
destinationType: Camera.DestinationType.FILE_URI
};
Camera.getPicture(options)
.then((imageData) => {
console.log(imageData);
this.fileToUpload = imageData;
const base64Image = "data:image/jpeg;base64," + imageData;
this.preloadImage._img.src = base64Image;
this.codeservice.doProfileImageUpload(base64Image)
.subscribe(res => {
if(res.length()>0){
console.log('updated');
}
})
}, (err) => {
console.log(err);
});

Related

Cordova Ionic Native File plugin - Where does it store the files in iOS?

I been trying to save a file on iOS. Right now I been running through Xcode right to my phone.
When I run the app it says that is saved successfully. But I don’t see any file when I use a file manager app like FileApp, FileManager, iCloud and the Apple crappy Files app.
My question is that I heard from a web search that in order to save the file iOS creates a sandbox folder for the app.
If I been saving it to this.file.documentDirectory, how can a user open it in let’s say Pages or Numbers apps? (You know Apple’s Word and Excel replacement for the uninitiated.)
Here’s the code.
writeToIOS(opts : {
fileName: string,
text: any
}) : Promise < IResponse < any >> {
let response: IResponse < boolean > = {
success: false,
error: '',
data: false
};
const options: IWriteOptions = {
replace: true
};
return new Promise((resolve, reject) => {
const path = this.file.documentsDirectory;
const directory = 'Attendance Log';
this
.file
.checkDir(path, directory)
.then(res => {
this
.file
.writeFile(path + directory, opts.fileName, opts.text, options)
.then(res => {
response = {
...response,
success: true,
error: res,
data: res
};
resolve(response);
})
.catch(error => reject(error));
})
.catch(() => {
this
.file
.createDir(path, directory, true)
.then(directory => {
this
.file
.writeFile(path + directory.name, opts.fileName, opts.text, options)
.then(res => {
response = {
...response,
success: true,
error: res,
data: res
};
resolve(response);
})
.catch(error => reject(error));
})
.catch(error => reject(error));
});
});
}
EDIT:
What the client/user should do is be able to choose the file and open it in his/her favorite app. That being a File Manager app or a Writer or Spreadsheet app.
I don't have too much experience with iOS, but I think you have chosen good dir.
cordova.file.documentsDirectory - Files private to the app, but that
are meaningful to other application (e.g. Office files). Note that for
OSX this is the user's ~/Documents directory. (iOS, OSX)
In iOS i would search /var/mobile/Applications/<UUID>/Documents
This is using the cordova-plugin-fileopener2 in conjuction with ionic native file opener:
const options = {
replace: true
};
const path = this.file.documentsDirectory;
const directory = 'Attendance Log';
this.file
.checkDir(path, directory)
.then(res => {
this.file
.writeFile(path + directory, opts.fileName, opts.text, options)
.then(res => {
this.fileOpener
.open(`${path}${directory}/${opts.fileName}` , 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
.then(() => ...)
.catch(error => ...);
})
.catch(error => ...);

Displaying a FILE_URI image taken by Native Camera in Ionic 3

How do you display a FILE_URI image taken by the user using #ionic-native/camera in Ionic 3?
I can use Ionic Native's Camera to get a FILE_URI image URL, with a result like this:
file:///var/mobile/Containers/Data/Application/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX/tmp/cdv_photo_005.jpg
However, When I try to display this image back to the user by referring to the URI in my view template, the image never loads.
Things I've tried:
-Using the image URI directly in the view
<img src="{{profile.image}}"> // Never loads
-Sanitizing the URI by including DomSanitizer in the page component:
<img [src]="domSanitizer.bypassSecurityTrustUrl(profile.image)"> // Never loads
I would rather not use a base64 image because of the performance drag. What am I doing wrong here?
import { normalizeURL } from 'ionic-angular'; ionic3 <img> tag src
<img *ngIf="base64Image" src="{{base64Image}}"/>
openCamera(pictureSourceType: any) {
let options: CameraOptions = {
quality: 95,
destinationType: this.camera.DestinationType.FILE_URI,
sourceType: pictureSourceType,
encodingType: this.camera.EncodingType.PNG,
targetWidth: 400,
targetHeight: 400,
saveToPhotoAlbum: true,
correctOrientation: true
};
this.camera.getPicture(options).then(imageData => {
if (this.platform.is('ios')) {
this.base64Image = normalizeURL(imageData);
// Alternatively if the problem only occurs in ios and normalizeURL
// doesn't work for you then you can also use:
// this.base64Image= imageData.replace(/^file:\/\//, '');
}
else {
this.base64Image= "data:image/jpeg;base64," + imageData;
}
}, error => {
console.log('ERROR -> ' + JSON.stringify(error));
});
}
Hi try to use File Path ionic plugin
path = "file:///var/mobile/Containers/Data/Application/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX/tmp/cdv_photo_005.jpg";
this.filePath.resolveNativePath(path)
.then(filePath => console.log(filePath))
.catch(err => console.log(err));
Please read the documentation
https://ionicframework.com/docs/native/file-path/
You can use the below code for display the image
savePhotoClick = () =>{
const options: CameraOptions = {
quality: 70,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE
}
this.camera.getPicture(options).then((imageData) => {
// imageData is either a base64 encoded string or a file URI
// If it's base64 (DATA_URL):
this.base64Image = 'data:image/jpeg;base64,' + imageData;
}, (err) => {
// Handle error
});
Then use the img tag for display
<img [src]="base64Image" *ngIf="base64Image" />

Upload image ionic via httpClient

My backen looks like this. The backend required a file and 2 string params
#multipart/form-data
file: File,
title: string,
content: string
I used to use to select file then upload it to server via httpClient and formData
const formData = new FormData();
formData.append('title', form.value.title);
formData.append('content', form.value.description);
formData.append('file', this.img);
this.http.post(this.apiUrl + '/img', formData, settings);
Everything works just fine.
But now I decide that I do not want to use any more. I decide to use native camera
getPictureFromCamera() {
return new Promise((resolve, reject) => {
const options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE
}
this.camera.getPicture(options).then((imageData) => {
let base64Image = null;
//get photo from the camera based on platform type
base64Image = normalizeURL(imageData);
resolve(base64Image);
}, (error) => {
console.debug("Unable to obtain picture: " + error, "app");
reject(error);
});
})
}
I successfully can take and display the picture. The problem is that my function only return the path of image (not the file). How can I get the actual file so I can use form-data and httpClient to post it to my server.
I want to use my old formdata function so I just need a file. Is there any way I just only get a file from imgPath.
Note: when I log 'base64Image' (you can see in the code above)
http://localhost:8080/var/mobile/Containers/Data/Application/85D7DD14-849C-4ADE-9005-D8165CC2A55B/tmp/cdv_photo_001.jpg

How send string/image base64 to Sailsjs - Skipper with ajax

Currently I am capturing the image of the camera, this Base64 format,and I'm sending through ajax.
xhr({
uri: 'http://localhost:1337/file/upload',
method: 'post',
body:'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAA...'
}
0 file(s) uploaded successfully!
Here is a nice link that will guide you to do send an image from an Ajax Client to an ajax server.
http://www.nickdesteffen.com/blog/file-uploading-over-ajax-using-html5
You can read this sails documentation to receive files on a sails server :
http://sailsjs.org/documentation/reference/request-req/req-file
You can do as the following example :
Client side ( ajax ):
var files = [];
$("input[type=file]").change(function(event) {
$.each(event.target.files, function(index, file) {
var reader = new FileReader();
reader.onload = function(event) {
object = {};
object.filename = file.name;
object.data = event.target.result;
files.push(object);
};
reader.readAsDataURL(file);
});
});
$("form").submit(function(form) {
$.each(files, function(index, file) {
$.ajax({url: "/ajax-upload",
type: 'POST',
data: {filename: file.filename, data: file.data}, // file.data is your base 64
success: function(data, status, xhr) {}
});
});
files = [];
form.preventDefault();
});
Server side ( sails ) :
[let's say you have a model Picture that take an ID and a URL]
[here is a sample of Picture controller, just to give you an idea]
module.exports = {
uploadPicture: function(req, res) {
req.file('picture').upload({
// don't allow the total upload size to exceed ~10MB
maxBytes: 10000000
},
function onDone(err, uploadedFiles) {
if (err) {
return res.negotiate(err);
}
// If no files were uploaded, respond with an error.
if (uploadedFiles.length === 0){
return res.badRequest('No file was uploaded');
}
// Save the "fd" and the url where the avatar for a user can be accessed
Picture
.update(777, { // give real ID
// Generate a unique URL where the avatar can be downloaded.
pictureURL: require('util').format('%s/user/pictures/%s', sails.getBaseUrl(), 777), // GIVE REAL ID
// Grab the first file and use it's `fd` (file descriptor)
pictureFD: uploadedFiles[0].fd
})
.exec(function (err){
if (err) return res.negotiate(err);
return res.ok();
});
});
}
};
Hope this will help in your research.
I also recommand you to use Postman to test your API first, then code your client.

File upload in ionic (image or any file)?

can any one please sort it out it gives error FileTransfer is not defined.
Below is my code
controller("ExampleController", function($scope, $cordovaFileTransfer) {
$scope.upload = function() {
var options = {
fileKey: "avatar",
fileName: "yedu.jpg",
chunkedMode: false,
mimeType: "image/jpg"
};
$cordovaFileTransfer.upload("http://192.168.1.109/uploads/upload", "/android_asset/www/img/yedu.jpg", options).then(function(result) {
console.log("SUCCESS: " + JSON.stringify(result.response));
}, function(err) {
console.log("ERROR: " + JSON.stringify(err));
}, function (progress) {
// constant progress updates
});
}
});
I think you getting error in browser . As per the official documentation of plugin this plugin is not supported to browser for more details go to here and here.
If you testing in browser then before installing app in device add the cordovaFileTransfer plugin to your project.
cordova plugin add org.apache.cordova.file-transfer
And for the full implementation of file upload and download with cordova you may go to here.