I'm unable to get the size of a file to upload with nativescript - firebase

I'm trying evaluate the mime-type and the size of a image uploaded using nativescript-imagepicker. However seems like the module itself can't do it. How can I apply constraits to the file I'm uploading? (Like max size or just png or jpg)
There's my code:
const context = imagepicker.create({ mode: "single" });
context
.authorize()
.then(() => {
console.log('imagePicker.authorize...');
return context.present();
})
.then((selection) => {
if (!selection || !selection.forEach) {
console.log('Error on selection empty or not array:', selection);
return;
}
selection.forEach((selected) => {
this.processPhoto(selected);
});
}).catch((err) => {
.
.
.
Processing the image...
processPhoto (selectedPhoto: any) {
console.log('uploading photo to firebase', selectedPhoto);
this.firebaseService.getImagePickerLocalFilePath(selectedPhoto)
.then((localFilePath: string) => {
console.log('about to upload file:', localFilePath);
return this.firebaseService.uploadFile(localFilePath);
})
.catch((err) => {
this.isLoading = false;
this.messageService.handleErrorRes(err);
});
}

You will have to read the size & extension on File and prevent upload when they do not match your constraints.
const file = fileSystemModule.fromPath(localFilePath);
if (file.size <= YOUR_SIZE_LIMIT_IN_BYTES && file.extension.toLowerCase() === "png") {
// Upload
} else {
alert("File can't be uploaded");
}

Related

How to unzip to a folder using yauzl?

I am trying to use yauzl to unzip files. However the example in the repo does not show how to unzip to a folder. It simply says:
readStream.pipe(somewhere);
Is there an easy way to extract the contents to a folder?
Hi :) Replacing 'readStream.pipe(somewhere);' with code under '//--------------------' tag below works for me and the example in the repo
import fs = require('fs');
const unzipper = require('unzipper');
const { pipeline, finished } = require('stream');
//--------------------
cons destDir = 'C:\MyPath'
const writer = fs.createWriteStream(path.join(destDir, entry.fileName));
readStream.pipe(writer);
await finished(readStream, (err) => {
if (err) {
console.error(' ### Streaming to writer failed: ', err);
} else {
console.log(' ### Streaming to writer succeded, file unzipped.');
}
};
DISCLAIMER: I am at the beginning of learning Node/ts! This works for me, but may be wrong to some reason/s.
Here's a promise returning function that does what you're asking with the following caveats:
I have used mkdirp external library. This can be removed if you're more careful with how you create your directories.
I have not tested unzipping on top of an existing directory.
The zipFile.close() statements before the rejects may be unnecessary.
import path = require('path');
import yauzl = require('yauzl');
import mkdirp = require('mkdirp');
/**
* Example:
*
* await unzip("./tim.zip", "./");
*
* Will create directories:
*
* ./tim.zip
* ./tim
*
* #param zipPath Path to zip file.
* #param unzipToDir Path to the folder where the zip folder will be put.
*/
const unzip = (zipPath: string, unzipToDir: string) => {
return new Promise<void>((resolve, reject) => {
try {
// Create folder if not exists
mkdirp.sync(unzipToDir);
// Same as example we open the zip.
yauzl.open(zipPath, { lazyEntries: true }, (err, zipFile) => {
if (err) {
zipFile.close();
reject(err);
return;
}
// This is the key. We start by reading the first entry.
zipFile.readEntry();
// Now for every entry, we will write a file or dir
// to disk. Then call zipFile.readEntry() again to
// trigger the next cycle.
zipFile.on('entry', (entry) => {
try {
// Directories
if (/\/$/.test(entry.fileName)) {
// Create the directory then read the next entry.
mkdirp.sync(path.join(unzipToDir, entry.fileName));
zipFile.readEntry();
}
// Files
else {
// Write the file to disk.
zipFile.openReadStream(entry, (readErr, readStream) => {
if (readErr) {
zipFile.close();
reject(readErr);
return;
}
const file = fs.createWriteStream(path.join(unzipToDir, entry.fileName));
readStream.pipe(file);
file.on('finish', () => {
// Wait until the file is finished writing, then read the next entry.
// #ts-ignore: Typing for close() is wrong.
file.close(() => {
zipFile.readEntry();
});
file.on('error', (err) => {
zipFile.close();
reject(err);
});
});
}
}
catch (e) {
zipFile.close();
reject(e);
}
});
zipFile.on('end', (err) => {
resolve();
});
zipFile.on('error', (err) => {
zipFile.close();
reject(err);
});
});
}
catch (e) {
reject(e);
}
});
}

react-native-sqlite-storage How to open the specified directory file?

my db in: android\app\src\main\assets\app.db
The way i tried:
open() {
SQLiteStorage.DEBUG(true);
SQLiteStorage.openDatabase({
name: 'file:///android_asset/app.db',
})
.then(() => {
console.info('');
})
.catch(err => {
console.warn(err);
});
}
But error:
How can i do this?
run ok!
open() {
SQLiteStorage.DEBUG(true);
SQLiteStorage.openDatabase({
name: 'app.db', // android/app/src/main/assets/app.db
})
.then(() => {
console.info('');
})
.catch(err => {
console.warn(err);
});
}
In react-native-cli:
1- It is convenient first of all to make sure that the database exists in the documents directory, with rn-fetch-blob you can list the documents that are in a directory like this:
import RNFetchBlob from 'rn-fetch-blob';
let dirs = RNFetchBlob.fs.dirs;
const documentPath = dirs.DocumentDir;
const externalZipPath = dirs.DCIMDir;
RNFetchBlob.fs.ls (documentPath) .then ((files) => {
console.log (files)
})
If you do not carry out this step, you can set that a basic database is being created and opened as it does not find any with that name.
You can also open the database from android studio:
When Launch succeeded:
In Device File Explorer> data> data> com.nameofyourapp> databases
You can also click on the bottom tab of android studio 'Database inspector' to see the database changes in real time.
2- Once you are sure that a database already exists in that directory:
To open the database in directories inside the cell phone but outside your project:
"If your folder is not in app bundle but in app sandbox i.e. downloaded from some remote location"
let openDbExample = () => {
let errorCB = (err) => {
console.log ("SQL Error:" + err);
}
let successCB = () => {
db.transaction ((tx) => {
tx.executeSql (
`SELECT * FROM name_column_table LIMIT 10`, [], (tx, results) => {
var len = results.rows.length;
for (let i = 0; i <len; i ++) {
let row = results.rows.item (i);
console.log (row);
}
})
})
}
if (Platform.OS === 'ios') {
db = SQLite.openDatabase ({name: "example_data_base.db", location:
'Documents'}, successCB, errorCB);
}
else {
db = SQLite.openDatabase ({name: "example_data_base.db", readOnly: true,
location: "default", createFromLocation: 2}, successCB, errorCB)
}
}

Ionic 3 - How to Upload a video file from gallery to Firebase storage

I have found many solutions for uploading images and audio to Firebase storage from Ionic 3 but not a single solution for uploading video file from gallery to Firebase storage. I have been going around Camera, File, File path, Plugins,etc but not seems to find a valid solution for uploading mp4 file from my gallery to Storage.
I have tried this at first (but it has not worked):
uploadpage.ts
async selectVideo(){
const options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.DATA_URL,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
// encodingType: this.camera.EncodingType,
mediaType: this.camera.MediaType.ALLMEDIA
}
let result = await this.camera.getPicture(options);
result.then((uri) => {
this.spinner.load();
this.selectedVideo = uri;
}, (err) => {
// Handle error
this.helper.presentToast(err.message);
});
}
//Upload video
uploadVideo(){
if(this.selectedVideo){
this.spinner.load();
//upload task
let upload= this.api.uploadVideo(this.selectedVideo)
upload.then().then(res => {
let otherData={title:this.title,category:this.type, thumbnail:this.thumbnail}
this.api.storeInfoToDatabase(res.metadata, otherData).then(()=>{
this.spinner.dismiss();
})
})
}
}
api.ts
uploadVideo(data): AngularFireUploadTask{
let newName = `${new Date().getTime()}.mp4`;
let footballerId = JSON.parse(localStorage.getItem('data')).uid;
return this.afStorage.ref(`videos/${newName}`).putString(data);
}
storeInfoToDatabase(metaInfo, data){
let toSave={
created:metaInfo.timeCreated,
url: metaInfo.downloadURLs[0],
fullPath: metaInfo.fullPath,
contentType: metaInfo.contentType,
footballerId:'',
title: data.title || '',
type:data.type || '',
thumbnail: data.thumbnail || '',
}
toSave.footballerId = JSON.parse(localStorage.getItem('data')).uid;
return this.addVideo(toSave);
}

Adding or deleting data in a file with Cloud Functions

my idea is to be able to edit files in storage.
This edition consists of adding or deleting file data according to the firebase trigger.
I created a trigger in firebase after obtaining the file with the bucket.file function ("file.txt"). CreateReadStream ()
and I edited the data in the base in the change in the firebase after this I updated the file with the function
bucket.file ("file.txt"). createWriteStream ().
This solution is good when there is 1 trigger, but when there are more than 2 triggers, the data does not keep correctly why the file is overwritten with the data it had before.
Example
this is the content of file.txt
This text is an example
and executed 2 triggers
the 2 activators get the file at the same time and the first trigger adds data and overwrites the file with this message
this text is an example
and this file was edited with the first trigger
and the second activator erases data and overwrites the file with this message
this text
When the triggers are finished, the file has "this text"
but this file must have
this text
and this file was edited with the first trigger
Someone help me.
exports.createData = functions.database.ref('data/{id}/summary/status').onCreate((data, context) => {
let status = data._data;
return Promise.all([ admin.database().ref('data/' + context.params.id + '/summary/entityUrl').once('value', (snapshot) => {
let entityUrl = snapshot.val();
if (isDataValid(status))
return addDataFile(entityUrl) ;
return;
}) ]);
})
function addDataFile(entityUrl){
return Promise.all([ returnFile("txt",() => {
dataFile.splice(dataFile.length - 1, 0, `new data ${entityUrl}`)
updateFileStorage("txt", dataFile.join('\n'));
}) ]);
}
function returnFile(extension, callback) {
let respData = "";
if (dataFile == null ){
return bucket.file(FileUrl + extension).createReadStream()
.on('data', (chunk) => {
respData += chunk;
})
.on('end', () => {
dataFile = respData.split('\n');
callback();
})
.on('error', (error) => {
console.log("Error en lectura")
return returnFile(extension, callback);
})
}
else callback();
return;
}
function updateFileStorage(extension,data, trys ){
trys = typeof trys !== 'undefined' ? trys : 0;
if(trys>6)
return;
var s = new Readable();
s._read = function noop() { };
s.push(data);
s.push(null);
return s.pipe(bucket.file(FileUrl + extension).createWriteStream())
.on('finish', function () {
//console.log("File updated");
return;
})
.on('error', function (err) {
console.log("Error de Escritura");
return setTimeout(() => {
return updateFileStorage(extension, data, trys + 1)
}, 250);
})
}

How to access image src nativescript

How can I get photo src, from nativescript camera module?
public takePicture() {
cameraModule.takePicture().then(function(picture) {
console.log("Result is an image source instance");
var image = new imageModule.Image();
image.imageSource = picture;
console.dir(picture);
});
}
console.dir output:
=== dump(): dumping members ===
{
"android": {
"constructor": "constructor()function () { [native code] }"
}
}
=== dump(): dumping function and properties names ===
loadFromResource()
fromResource()
loadFromFile()
fromFile()
loadFromData()
fromData()
loadFromBase64()
fromBase64()
setNativeSource()
saveToFile()
height: 480
width: 640
=== dump(): finished ===
How do I get the image src ?
I want to upload it to firebase, so i need the src.
To upload to firebase, you need to upload the image via its path:
let imgsrc = this.imageSource.fromNativeSource(data);
let path = this.utils.documentsPath(randomName);
imgsrc.saveToFile(path, this.enums.ImageFormat.png);
this.firebase.uploadFile(path).then((uploadedFile: any) => {
this.appSettings.setString("fileName", uploadedFile.name);
this.router.navigate(['/soundcloud']);
this.LoadingIndicator.hide();
}, (error: any) => {
alert("File upload error: " + error);
});
}, (err: any) => {
alert(err);
});
Figured it out, this works:
public takePicture() {
cameraModule.takePicture().then((picture) => {
var image = new imageModule.Image();
image.imageSource = picture;
let savePath = fs.knownFolders.documents().path;
let fileName = 'img_' + new Date().getTime() + '_' + this.currentUserId.getValue() + '.' + enumsModule.ImageFormat.jpeg;
let filePath = fs.path.join( savePath, fileName );
picture.saveToFile(filePath, enumsModule.ImageFormat.jpeg);
this.photoService.uploadImage(filePath, fileName).then((data) => {
this._router.navigate(["/upload", fileName, this.currentUserId.getValue()]);
});
});
}

Resources