Convert File to base64 in Nativescript - nativescript

I have been trying to get the base64 of a File of Nativescript, so far I have tried the next:
const documents: Folder = <Folder>knownFolders.documents();
const folder: Folder = <Folder>documents.getFolder("Download");
const file: File = <File>folder.getFile("Vista general Aguas.pdf");
const toBase64 = (fle: File) => new Promise((resolve, reject) => {
const reader = new FileReader();
const newFile = fle.readSync(err => console.log(err));
// I know that I have to convert the binary to base64, but I'm getting this [B#9b1d878 in newFile
reader.readAsDataURL(newFile);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
toBase64(file).then(result => console.log('64', result));
Any help is appreciated!

I have created function using native implementation. This function return base64 string.
public getBase64String = (path) => {
const sourceFile: fs.File = fs.File.fromPath(path);
const data = sourceFile.readSync();
if (isIOS) {
return data.base64EncodedStringWithOptions(0);
} else {
return android.util.Base64.encodeToString(
data,
android.util.Base64.NO_WRAP
);
}
};

Related

Visual regression in Cypress

I am doing a visual regression :
code: plugins/indexts
on('task', {
graphicsMatch: ({ img1Path, img2Path, diffImgPath }) => {
const img1 = PNG.sync.read(fs.readFileSync(img1Path));
const img2 = PNG.sync.read(fs.readFileSync(img2Path));
const { width, height } = img1;
const diff = new PNG({ width, height });
let pixelCount = pixelmatch(img1.data, img2.data, diff.data);
fs.writeFileSync(diffImgPath, PNG.sync.write(diff));
return pixelCount;
},
});
stepdef:
And('I capture the screenshot of {string}', (editorDocument: string) => {
cy.wait(5000);
cy.captureScreen(editorDocument).as('generatedFileName');
});
Then(
'the generated pdf is as expected {string} and {string}',
(nameOfFeatureFile: string, editorScreenshot: string) => {
filesApi.comparePixelDiff(
nameOfFeatureFile,
editorScreenshot,
Cypress.currentTest.title,
);
},
);
API's:
comparePixelDiff(
nameOfFeaturefile: string,
actualFileName: string,
expectedFileName: string,
) {
cy.get('#generatedFileName').then((receivedFileName) => {
const sourceFilePath = `${FilesApi.screesnShotsFolder}${FilesApi.visualTestingFeaturesFolder}/${nameOfFeaturefile}/${actualFileName}${FilesApi.graphicExt}`;
const expectedFilePath = `${FilesApi.expectedExportsFolder}${expectedFileName}${FilesApi.graphicExt}`;
const diffFilePath = `${FilesApi.actualExportsFolder}${actualFileName}-${FilesApi.graphicsDiffSufix}${FilesApi.graphicExt}`;
cy.task('graphicsMatch', {
img1Path: sourceFilePath,
img2Path: expectedFilePath,
diffImgPath: diffFilePath,
}).then((pixelsDiff) => {});
});
}
}
i am using pixelmatch here,i have used viewport as 1280x720 in json file locally it works fine but fails on CI as the resolution of screenshot is not persistent
i have even tried cy.viewport(1280, 720) before capturescreenshot it didnt work as well.
How do i fix this issue, please help.

How to run wasm on d8

I have a wasm file fib.wasm which contains function fib(n).
If run it in the browser, we can do
var module, functions = {};
fetch('fib.wasm')
.then(response => response.arrayBuffer())
.then(buffer => new Uint8Array(buffer))
.then(binary => {
var moduleArgs = {
wasmBinary: binary,
onRuntimeInitialized: function () {
functions.fib =
module.cwrap('fib',
'number',
['number']);
onReady();
}
};
module = Module(moduleArgs);
});
If in Node, since fetch is not implemented, we can do
const fs = require('fs')
const buf = fs.readFileSync('fib.wasm')
(async () => { res = await WebAssembly.instantiate(buf); })()
const { fib } = res.instance.exports
However, in d8 shell, both ways involves functions undefined. How can we run wasm in d8?
The d8 shell has a function read() which reads a file from disk. It takes an optional parameter to specify binary mode. So the following should work:
const buf = read('fib.wasm', 'binary');
let res;
WebAssembly.instantiate(buf).then((x) => res = x, (error) => console.log(error));
const { fib } = res.instance.exports;

how can i upload file by using xpath in cypress

How can upload file by using xpath in cypress?
Am getting as mentioned below error...
const xpath = require('cypress-xpath')
describe('File upload Demo', () => {
Cypress.Commands.add('uploadFile', { prevSubject: 'element' }, (subject, fileName) => {
console.log('subject', subject)
return cy.fixture(fileName, 'base64')
.then(Cypress.Blob.base64StringToBlob)
.then(blob => {
console.log('blob', blob)
const el = subject[0]
if (el != null) {
const testFile = new File([blob], fileName)
const dataTransfer = new DataTransfer()
dataTransfer.items.add(testFile)
el.files = dataTransfer.files
}
return subject
})
}
)
it('upload file test', () => {
cy.visit('https://tus.io/demo.html')
cy.xpath('//input[#type="file"]').upload('401k_deferral.xlsx')
cy.get('[class="button primary"]').should('have.class', 'button primary')
})
})
TypeError: cy.xpath(...).upload is not a function
The custom command you have added is called uploadFile but you are trying to call upload.
Try this:
cy.xpath('//input[#type="file"]').uploadFile('401k_deferral.xlsx')

Angularfire multiple upload

I want to upload few images and I have code as below. It returns the download link, but for only one image. How can I get a list of links to uploaded images?
constructor(private storage: AngularFireStorage, public afs: AngularFirestore, ) {
this.files = this.afs.collection('files').valueChanges();
}
uploadFile(event) {
// reset the array
this.uploads = [];
const filelist = event.target.files;
const allPercentage: Observable<number>[] = [];
for (const file of filelist) {
const filePath = `${file.name}`;
const fileRef = this.storage.ref(filePath);
const task = this.storage.upload(filePath, file);
const _percentage$ = task.percentageChanges();
allPercentage.push(_percentage$);
// observe percentage changes
this.uploadPercent = task.percentageChanges();
// get notified when the download URL is available
task.snapshotChanges().pipe(
finalize(() => {
this.downloadURL = fileRef.getDownloadURL();
})
).subscribe();
// this.downloadURLs.push(this.downloadURL);
}
}
uploadFile(files) {
//console.log(this.uploadService.uploadFile(file));
this.uploadService.uploadFile(files);
}
<ion-item>
<ion-input type="file" (change)="uploadFile($event)" multiple="multiple"></ion-input>
</ion-item>
<button (click)="onAddItem()" ion-button block>Добавить</button>
Easy way: Clear this.downloadURLs before uploaded, then add url in finalize step
uploadFile(event) {
// reset the array
this.uploads = [];
this.downloadURLs = [];
const filelist = event.target.files;
const allPercentage: Observable<number>[] = [];
for (const file of filelist) {
const filePath = `${file.name}`;
const fileRef = this.storage.ref(filePath);
const task = this.storage.upload(filePath, file);
const _percentage$ = task.percentageChanges();
allPercentage.push(_percentage$);
// observe percentage changes
this.uploadPercent = task.percentageChanges();
// get notified when the download URL is available
task.snapshotChanges().pipe(
finalize(() => {
fileRef.getDownloadURL().subscribe((url) => {
this.downloadURLs = this.downloadURLs.concat([url]);
});
})
).subscribe();
// this.downloadURLs.push(this.downloadURL);
}
}
Rxjs way: First combine all latest result, then subscribe to assign results. Note: You can use forkJoin too
import { combineLatest, from } from 'rxjs';
import { map, filter } from 'rxjs/operators';
...
uploadFile(event) {
// reset the array
this.uploads = [];
const filelist = event.target.files;
const allPercentage: Observable<number>[] = [];
const downloadUrls$ = filelist.map((file) => {
const filePath = `${file.name}`;
const fileRef = this.storage.ref(filePath);
const task = this.storage.upload(filePath, file);
const _percentage$ = task.percentageChanges();
allPercentage.push(_percentage$);
// observe percentage changes
this.uploadPercent = task.percentageChanges();
// get notified when the download URL is available
return task.snapshotChanges().pipe(
filter((task) => task.state === this.storage.TaskState.SUCCESS)
switchMap(() => from(fileRef.getDownloadURL()))
)
});
combineLatest(...downloadUrls$)
.subscribe((urls) => this.downloadURLs = urls)
}

Spot the difference between these two images

Programmatically, my code is detecting a difference between two classes of images, and always rejecting one class, while always allowing the other.
I have yet to find any difference between the images that yield the error and the ones that don't an yield error. But there has to be some difference, because the ones that yield an error do so 100% of the time, and the others work as expected 100% of the time.
In particular, I have inspected color format: RGB in both groups; size: no notable difference; datatype: uint8 in both; magnitude of pixel values: similar in both.
Below are two images that never work, followed by two images that always work:
This image never works: https://www.colourbox.com/preview/11906131-maple-tree-and-grass-silhouette.jpg
This image never works: http://feldmanphoto.com/wp-content/uploads/awe-inspiring-house-clipart-black-and-white-disney-coloring-pages-big-clipartxtras-illistration-background-housewives-bouncy.jpeg
This image always works: http://www.spacedesign.us/wp-content/uploads/landscape-with-old-tree-and-grass-over-white-background-black-and-black-and-white-trees.jpg
This image always works: http://www.modernhouse.co/wp-content/uploads/2017/07/1024px-RoseSeidlerHouseSulmanPrize.jpg
How can I spot the difference?
The scenario is that I am using Firebase with Swift iOS front end to send these images to a Google Cloud ML-engine hosted convnet. Some images work all the time and certain others never work as above. Further, all images work when I use the gcloud versions predict CLI. To me the issue is necessarily something in the images. Hence I am posting here for the imaging group. Code is included as requested for completeness.
CODE of index.js file is included:
'use strict';
const functions = require('firebase-functions');
const gcs = require('#google-cloud/storage');
const admin = require('firebase-admin');
const exec = require('child_process').exec;
const path = require('path');
const fs = require('fs');
const google = require('googleapis');
const sizeOf = require('image-size');
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();
const rtdb = admin.database();
const dbRef = rtdb.ref();
function cmlePredict(b64img) {
return new Promise((resolve, reject) => {
google.auth.getApplicationDefault(function (err, authClient) {
if (err) {
reject(err);
}
if (authClient.createScopedRequired && authClient.createScopedRequired()) {
authClient = authClient.createScoped([
'https://www.googleapis.com/auth/cloud-platform'
]);
}
var ml = google.ml({
version: 'v1'
});
const params = {
auth: authClient,
name: 'projects/myproject-18865/models/my_model',
resource: {
instances: [
{
"image_bytes": {
"b64": b64img
}
}
]
}
};
ml.projects.predict(params, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
});
}
function resizeImg(filepath) {
return new Promise((resolve, reject) => {
exec(`convert ${filepath} -resize 224x ${filepath}`, (err) => {
if (err) {
console.error('Failed to resize image', err);
reject(err);
} else {
console.log('resized image successfully');
resolve(filepath);
}
});
});
}
exports.runPrediction = functions.storage.object().onChange((event) => {
fs.rmdir('./tmp/', (err) => {
if (err) {
console.log('error deleting tmp/ dir');
}
});
const object = event.data;
const fileBucket = object.bucket;
const filePath = object.name;
const bucket = gcs().bucket(fileBucket);
const fileName = path.basename(filePath);
const file = bucket.file(filePath);
if (filePath.startsWith('images/')) {
const destination = '/tmp/' + fileName;
console.log('got a new image', filePath);
return file.download({
destination: destination
}).then(() => {
if(sizeOf(destination).width > 224) {
console.log('scaling image down...');
return resizeImg(destination);
} else {
return destination;
}
}).then(() => {
console.log('base64 encoding image...');
let bitmap = fs.readFileSync(destination);
return new Buffer(bitmap).toString('base64');
}).then((b64string) => {
console.log('sending image to CMLE...');
return cmlePredict(b64string);
}).then((result) => {
console.log(`results just returned and is: ${result}`);
let predict_proba = result.predictions[0]
const res_pred_val = Object.keys(predict_proba).map(k => predict_proba[k])
const res_val = Object.keys(result).map(k => result[k])
const class_proba = [1-res_pred_val,res_pred_val]
const opera_proba_init = 1-res_pred_val
const capitol_proba_init = res_pred_val-0
// convert fraction double to percentage int
let opera_proba = (Math.floor((opera_proba_init.toFixed(2))*100))|0
let capitol_proba = (Math.floor((capitol_proba_init.toFixed(2))*100))|0
let feature_list = ["houses", "trees"]
let outlinedImgPath = '';
let imageRef = db.collection('predicted_images').doc(filePath.slice(7));
outlinedImgPath = `outlined_img/${filePath.slice(7)}`;
imageRef.set({
image_path: outlinedImgPath,
opera_proba: opera_proba,
capitol_proba: capitol_proba
});
let predRef = dbRef.child("prediction_categories");
let arrayRef = dbRef.child("prediction_array");
predRef.set({
opera_proba: opera_proba,
capitol_proba: capitol_proba,
});
arrayRef.set({first: {
array_proba: [opera_proba,capitol_proba],
brief_description: ["a","b"],
more_details: ["aaaa","bbbb"],
feature_list: feature_list},
zummy1: "",
zummy2: ""});
return bucket.upload(destination, {destination: outlinedImgPath});
});
} else {
return 'not a new image';
}
});
Issue was that the bad images were grayscale, not RGB as expected by my model. I initially had checked this first by looking at the shape. But the 'bad' images had 3 color channels, each of those 3 channels stored the same number --- so my model was refusing to accept them. Also, as expected and contrary to what I initially thought I observed, turns out the gcloud ML-engine predict CLI actually also failed for these images. Took me 2 days to figure this out!

Resources