Showing a loading message until the blob file is downloaded - reactjs

I am printing a bill as a pdf document after submitting the billing form. The service that is downloading the blob file is as follows.
export default [createLogic({
type: reportTypes.REPORT,
latest: true,
debounce: 2000,
process({ MockHTTPClient, getState, action }, dispatch, done) {
dispatch(reportActions.queryStart())
let HTTPClient;
if (MockHTTPClient) {
HTTPClient = MockHTTPClient;
} else {
HTTPClient = API;
}
HTTPClient.Post(endPoints.REPORTS_BILL, action.payload.reportOptions)
.then(
(resp) => {
return resp.data
})
.then((data) => {
dispatch(reportActions.getReportSuccess(data));
var link = document.createElement('a');
link.href = `data:application/octet-stream;base64,${data}`;
var today = new Date();
var date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds() + ":" + today.getMilliseconds();
var dateTime = date + ' ' + time;
var fileName = dateTime + "billing.pdf";
link.download = fileName;
link.click();
var base64str = data;
var binary = atob(base64str.replace(/\s/g, ''));
var len = binary.length;
var buffer = new ArrayBuffer(len);
var view = new Uint8Array(buffer);
for (var i = 0; i < len; i++) {
view[i] = binary.charCodeAt(i);
}
var blob = new Blob([view], { type: "application/pdf" });
var url = URL.createObjectURL(blob);
window.open(url);
dispatch(reportActions.getReportSuccess(data))
})
.then(() => dispatch(reportActions.queryEnd()))
.catch(err => {
dispatch(reportActions.getReportFailed());
var errorMessage = "Failed to get prductivity data.";
if (err && err.code == "ECONNABORTED") {
errorMessage = "Please check your internet connection.";
}
dispatch(
reportActions.getReportFailed({
title: "Error!",
message: errorMessage
})
);
})
.then(() => done());
}
})
]
In the Billing Component following is the method that I am calling the service.
printBill = () => {
debugger;
var reportType = 1;
var reportFiltersSet = {};
if (this.billingOptions.length > 0) {
this.billingOptions.map(v => {
reportFiltersSet[v.name] = v.value;
});
}
this.props.reportActions.queryStart();
var reportType = 1; //Thiis need to be dynamic. use this => //this.state.reportType
var reportFilters = this.state.billingOptions;
if (
reportFiltersSet.organization == undefined ||
reportFiltersSet.department == undefined ||
reportFiltersSet.division == undefined ||
reportFiltersSet.billYear == undefined ||
reportFiltersSet.billMonth == undefined
) {
this.setState({
reportContentNull: true,
warning: "Error!",
errorMessage:
"Either department or division reqiured with organization , year and month",
negative: true,
hidden: false
});
this.props.reportActions.getReport({ reportOptions: reportFiltersSet });
var reportDownloadType = this.state.reportType;
};
I can download the blob file , when I submit the form without any problem. But in user's perspective it is important to show that the loading state in order to have a better user experince. Therefore can anyone help me out to show a loading message during the submit and loading the blob file?

So the Idea is to start loading as soon as HTTP calls happens and remove it when response is recieved.
Simple way would be add a loading variable in state and in render check that variable and show spinner.
onClick = () => {
this.setState({ loading: true }, () => {
Axios.get('/sampelCall')
.then(result => this.setState({
loading: false,
data: [...result.data],
}));
});
}
render() {
const { data, loading } = this.state;
return (
<div>
<button onClick={this.onClick}>
Load Data
</button>
{loading ? <LoadingSpinner /> : <ResultsTable results={data} />} // if loading in true will show Spinner
</div>
);
}
Note:
You need to handle loading variable in all cases (Success/Error) else Spinner will keep on loading.

Related

Memory leak warnings in electron

I'm getting memory leak warning in the console for my Electron app, i don't know what to do to increase limit. It's causing it everytime i run the app.
Does the error is linked to uiohook? Or did i miss something here?
How can i use emitter.setMaxListeners() in my case? I have no clue of how to fix it, and hwo to increase the memory leak.
[3452:1014/104426.056:ERROR:service_worker_storage.cc(1904)] Failed to delete the database: Database IO error
(node:21792) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 terminate-timer listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit
(Use `electron --trace-warnings ...` to show where the warning was created)
(node:21792) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 set-activity listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit
Electron
const electron = require('electron');
const BrowserWindow = electron.BrowserWindow;
const dialog = electron.dialog;
const desktopCapturer = electron.desktopCapturer;
const idle = electron.powerMonitor;
const remote = electron.remote;
const notification = electron.Notification;
const globalShortcut = electron.globalShortcut;
const screen = electron.screen;
const ipcMain = electron.ipcMain;
const app = electron.app;
const isDev = require('electron-is-dev');
const path = require('path');
const activeWindows = require('electron-active-window');
const activeWindowPage = require('active-win');
const BMParser = require('bookmark-parser');
const axios = require('axios');
const uiohook = require('uiohook-napi');
const { autoUpdater } = require("electron-updater");
const debug = require('debug')('Franz:ipcApi:autoUpdate');
const dns = require("dns");
const activity = { is_mouse: 0, is_keyboard: 0 };
const headers = {
'Content-Type': 'application/json;charset=UTF-8',
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Origin": "*",
"Accept": "application/json"
}
const sessionUser = null;
let updateInterval = null;
app.disableHardwareAcceleration();
electron.powerSaveBlocker.start('prevent-app-suspension');
//electron.commandLine.appendSwitch ("disable-http-cache");
// Change App Name on Windows
if (process.platform === 'win32')
{
app.setAppUserModelId('Rubii');
}
let apiEndpoint = "http://creaz:81/xorix/api"; // Brian
let frameUrl = 'http://localhost:3000'; // Brian
//if (isDev) { // or if(process.env.NODE_ENV)
// apiEndpoint = "http://creaz:81/xorix/api";
// frameUrl = 'http://localhost:3000';
//}
var internetAvailable = require("internet-available");
let isConnected = false;
let counterInternet = 0;
let allowSendInternetNotification = 1;
async function liveInternetCheck() {
var userSessionCheck = await getSessionUser();
// Most easy way
internetAvailable({
domainName: "rubii.com",
// Provide maximum execution time for the verification
timeout: 10000,
// If it tries 10 times and it fails, then it will throw no internet
retries: 10
}).then(() => {
// Available Internet
isConnected = true;
counterInternet++;
if(counterInternet > 3 && allowSendInternetNotification == 0) {
allowSendInternetNotification = 1;
}
}).catch(() => {
// Not available internet
isConnected = false;
if(isConnected == false && userSessionCheck && allowSendInternetNotification == 1) {
var message = 'Your internet has been disconnected! Please login again';
new notification({ title: 'Ooops', body: message }).show();
// Logout the user in the other end
win.webContents.send("terminate-timer", "hello");
allowSendInternetNotification = 0;
counterInternet = 0;
}
});
}
autoUpdater.on("update-available", (_event, releaseNotes, releaseName) => {
const dialogOpts = {
type: 'info',
buttons: ['Ok'],
title: 'Update Available',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail: 'A new version download started. The app will be restarted to install the update.'
};
dialog.showMessageBox(dialogOpts);
updateInterval = null;
});
autoUpdater.on("update-downloaded", (_event, releaseNotes, releaseName) => {
const dialogOpts = {
type: 'info',
buttons: ['Restart'],
title: 'Application Update',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail: 'A new version has been downloaded. Restart the application to apply the updates.'
};
dialog.showMessageBox(dialogOpts).then((returnValue) => {
if (returnValue.response === 0) autoUpdater.quitAndInstall()
});
});
function checkUpdate() {
updateInterval = setInterval(() => autoUpdater.checkForUpdates(), 600000);
}
let win;
ipcMain.on('close-me', (evt, arg) => {
new notification({ title: 'Ooops', body: 'We hope to see you again!' }).show();
app.quit()
});
function determineScreenShotSize() {
var screenSize = screen.getPrimaryDisplay().workAreaSize
return {
width: screenSize.width,
height: screenSize.height
}
}
async function takeScreenshot() {
var user = await getSessionUser();
var timer = await getSessionTimer();
if (user && timer) {
if (timer.timer == 1) {
//console.log('Gathering screens...');
//console.log(app.getPath('pictures'));
const thumbSize = determineScreenShotSize();
const workaroundTimestamp = Date.now();
const options = {
types: ['screen'],
thumbnailSize: { ...thumbSize, workaroundTimestamp }
};
desktopCapturer.getSources(options).then((sources) => {
console.log('Sources received:' + sources.length);
sources.forEach(function (source) {
const sourceName = source.name.toLowerCase();
//console.log(sourceName);
if (['entire screen', 'screen 1'].includes(sourceName)) {
var the_screenshot = source.thumbnail.toPNG();
var data = {
user_id: user.id,
company_id: timer.company_id,
image: the_screenshot.toString('base64')
}
axios.post(apiEndpoint + "/desktop/save_screenshots", data, {
headers: headers
})
.then((response) => {
// console.log(response);
})
.catch((error) => {
//console.log(error);
})
}
})
}).catch(console.error);
}
}
}
function saveSoftware() {
(async () => {
var options = [];
var software = await activeWindowPage();
var user = await getSessionUser();
var timer = await getSessionTimer();
if (user && timer) {
if (timer.timer == 1) {
software.user = user;
software.timer = timer;
axios.post(apiEndpoint + "/desktop/save_app", software, {
headers: headers
})
.then((response) => {
//console.log(response);
})
.catch((error) => {
//console.log(error);
})
}
}
})();
}
function getSessionUser() {
return win.webContents.executeJavaScript('sessionStorage.getItem("user");', true)
.then(result => {
if (result) {
return JSON.parse(result);
}
});
}
function getSessionTimer() {
return win.webContents.executeJavaScript('sessionStorage.getItem("timer");', true)
.then(result => {
if (result) {
return JSON.parse(result);
}
});
}
async function generateActivity() {
win.webContents.send("set-activity", activity);
// We reset after we send it
activity.is_mouse = activity.is_keyboard = 0;
}
function secondsToHms(d) {
d = Number(d);
var h = Math.floor(d / 3600);
var m = Math.floor(d % 3600 / 60);
var s = Math.floor(d % 3600 % 60);
var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : "";
var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : "";
var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : "";
return hDisplay + mDisplay + sDisplay;
}
function createWindow() {
win = new BrowserWindow({
width: 1200,
height: 900,
frame: true,
webPreferences: {
webSecurity: false,
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false,
backgroundThrottling: false
}
});
//win.loadURL('https://desktop.rubii.com');
win.loadURL(frameUrl, { "extraHeaders": "pragma: no-cache\n" });
// http://localhost:3000
//win.webContents.openDevTools();
//win.removeMenu(); // Brian
// or set the Menu to null
//win.setMenu(null); // Brian
// Reload cache
win.webContents.reloadIgnoringCache();
// Keyboard activity
uiohook.uIOhook.on('keydown', (e) => {
//console.log('Keyboard!')
activity.is_keyboard = 1;
})
// Mouse activity
uiohook.uIOhook.on('mousemove', (e) => {
//console.log('mouse');
activity.is_mouse = 1;
})
// Start listener for keyboard and mouse
uiohook.uIOhook.start();
win.on('close', function () {
win = null;
})
}
app.whenReady().then(createWindow).then(checkUpdate);
app.on('window-all-closed', function () {
app.quit();
});
app.on('activate', function () {
if (win == null) {
createWindow();
}
})
setInterval(takeScreenshot, 10 * 60 * 1000); // 10 minutes
setInterval(saveSoftware, 5 * 1000); // 5 seconds
setInterval(generateActivity, 1 * 1000);
setInterval(function() { liveInternetCheck(); }, 10 * 1000); // 10 seconds
Render
ipcRenderer.on("terminate-timer", function (event, data) {
// Logout if there is no internet connection
handleLogout();
});
// Set activity if there were any keyboard, mouse
ipcRenderer.on("set-activity", function (event, data) {
// If the timer is on
if(timer) {
setActivity(data);
}
});

React set state not updating object data

I'm trying to update state using handleChangeProps method, but some how finally the fields.fileName is set as empty string instead of actual value. I'm using material-ui DropZone for file and for name TextField. The addNsmFile is called when onSubmit is called. The remaining fields: name, fileData are not empty and the actual value is set and I can get them in addNsmFile function. Can you help me to figure out why fields.fileName is set as empty finally?
const [fields, setFields] = useState({
name : '',
fileName: '',
fileData: ''
})
const handleChangeProps = (name, value) => {
if (name === 'name' ) {
if (validator.isEmpty(value.trim())) {
setNameError('Enter NSM Name')
} else if (value.trim().length > 512) {
setNameError('The maximum length for NSM name is 512. Please re-enter.')
} else {
setNameError('')
}
}
if (name === 'fileData') {
console.log('fileData', value)
if (validator.isEmpty(value.trim())) {
setFileuploadError('Drag and drop or browse nsm file')
} else {
setFileuploadError('')
}
}
setFields({ ...fields, [name]: value })
}
const addNsmFile = () =>{
let nsmForm = new FormData()
nsmForm.append('name', fields.name)
nsmForm.append('fileName', fields.fileName)
nsmForm.append('fileData', fields.fileData)
NSMDataService.addFile(nsmForm).then((response)=>{
if (response.data.substring(0, 1) === '0') {
const results = JSON.parse(response.data.substring(2))
addNotification('success', 'NSM file is being added successfully.')
//props.onRowSelectionChange(results.addFile)
props.setOpenDialog(false)
props.setRefresh(results.addFile[0].id)
} else if (response.data.substring(0, 1) === '1') {
addNotification('error', response.data.substring(2))
props.setOpenDialog(false)
}
}).catch((error)=>{
console.log(error)
})
}
<DropzoneArea
acceptedFiles={[".csv, text/csv, application/vnd.ms-excel, application/csv, text/x-csv, application/x-csv, text/comma-separated-values, text/x-comma-separated-values"]}
maxFileSize={1000000000} //1GB
dropzoneText='Drag and drop a NSM file here or click to add'
showFileNames= {true}
showPreviews={false}
useChipsForPreview={true}
showAlerts={true}
filesLimit={1}
classes={{root:classes.rootDropzoneArea, icon: classes.iconDropzoneArea, text: classes.textDropzoneArea}}
onChange={(files) => {
files.forEach((file) => {
console.log(file)
handleChangeProps('fileName', file.name)
let reader = new FileReader()
reader.onload = function(event) {
let contents = event.target.result
handleChangeProps('fileData', contents)
console.log("File contents: " + contents)
}
reader.onerror = function(event) {
console.error("File could not be read! Code " + event.target.error.code)
}
reader.readAsText(file);
})
}}
onDelete={(file)=> {
handleChangeProps('fileData', '')
}
}
/>
I think the problem might be with your setFields() update in handleChangeProps. Try to do like this:
setFields(prevState => ({
...prevState,
[name]: value,
}))

Is it possible to read xlsx in react if office is not installed on windows machine?

Currently I am using below code to read xlsx file in react when my system having office (excel) installed. But the same is throwing error on other machine where office(excel) is not installed.
Error is at this point console.log(this.state.file.type)
Here is console.log :
lastModified: 1595606065652
lastModifiedDate: Fri Jul 24 2020 15:54:25 GMT+0000 (Greenwich Mean Time) {}
name: "ExamAnswer.xlsx"
size: 14266
type: "" // here type is null
webkitRelativePath: ""
__proto__: File
So, could you please tell how to read file type
handleExamInputFile() {
const reader = new FileReader();
const rABS = !!reader.readAsBinaryString;
console.log("file", this.state.file);
console.log(this.state.file.type);
let fileType =
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
if (this.state.file.size > 0) {
console.log(this.state.file.size);
if (this.state.file.type === fileType) {
if (rABS) {
reader.readAsBinaryString(this.state.file);
} else {
reader.readAsArrayBuffer(this.state.file);
}
reader.onload = (e) => {
const bstr = e.target.result;
const wb = XLSX.read(bstr, {
type: rABS ? "binary" : "array",
bookVBA: true,
});
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
const data = XLSX.utils.sheet_to_json(ws, {
raw: true,
});
const header = [];
const columnCount = XLSX.utils.decode_range(ws["!ref"]).e.c + 1;
for (let i = 0; i < columnCount; ++i) {
if (ws[`${XLSX.utils.encode_col(i)}1`] != undefined) {
header[i] = ws[`${XLSX.utils.encode_col(i)}1`].v;
}
}
console.log(header);
let headerMustHave = ["Exam Name", "EId", "Name"];
// let ifFound = header.every(function (val) {
// console.log(val);
// return headerMustHave.indexOf(val) !== -1;
// });
let checker = (arr, target) => target.every((v) => arr.includes(v));
let ifFound = checker(header, headerMustHave);
console.log(ifFound);
if (ifFound === true) {
for (var i = 0; i < data.length; i++) {
let excel_date = this.ExcelDateToJSDate(data[i]["Report Date"]);
data[i]["Report Date"] = excel_date;
}
this.setState({
data: data,
result: JSON.stringify(data),
cols: make_cols(ws["!ref"]),
});
const exceldata = JSON.parse(this.state.result);
const excelList = exceldata.map((data) => data);
const excel = { data: excelList };
const url = "http://localhost:8000/upload";
const config = {
headers: {
Accept: "*",
"Content-Type": "application/json",
"Allow-Control-Allow-Origin": "*",
// Accept: "application/json",
},
};
return post(url, excel, config).then((response) => {
toast.success(response.data, {
position: toast.POSITION.TOP_CENTER,
});
document.getElementById("file1").value = "";
this.setState({ file: "" });
});
} else {
toast.error("Some columns are not presented in uploaded file.", {
position: toast.POSITION.TOP_CENTER,
autoClose: 3000,
});
this.setState({ file: "" });
}
};
} else {
toast.error(
"This file format is not supported. Please select an .xlsx file.",
{
position: toast.POSITION.TOP_CENTER,
autoClose: 3000,
}
);
this.setState({ file: "" });
}
} else {
toast.error("Please select .xlsx file to upload.", {
position: toast.POSITION.TOP_CENTER,
autoClose: 3000,
});
this.setState({ file: "" });
}
}
Alternatively, is it possible to read the same xlsx file through python on above type machine?
TIA
Since this is React.js code, it's running client-side, in a browser.
Your problem with type being empty is that not all machines and browsers know how to map the file type .xlsx to the MIME type 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; those with Excel, or maybe LibreOffice installed, certainly might, but even that's not a given. Whether or not Excel is actually installed has no bearing on whether the XLSX.js library you're using can actually parse the file (since the browser doesn't know about Excel).
As I mentioned in the comments, you can simply optionally look at the extension of the file uploaded – and even that's not necessary; you could just attempt to pass the file to XLSX; it would fail to parse files that are not XLSX documents anyway.
Here's a refactoring of your code to move to promise-based asynchronicity, moving the actual processing code out of the React component, so it's more easily testable.
In addition, you seemed to be doing some strange to-JSON-from-JSON coercion before posting the data; I got rid of that (and all of the Toast error handling for a more minimal example)...
function ExcelDateToJSDate(x) {
return x; // TODO: implement
}
function processWorkbook(wb) {
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
const data = XLSX.utils.sheet_to_json(ws, {
raw: true,
});
const header = [];
const columnCount = XLSX.utils.decode_range(ws["!ref"]).e.c + 1;
for (let i = 0; i < columnCount; ++i) {
const col = `${XLSX.utils.encode_col(i)}1`;
if (ws[col] != undefined) {
header[i] = ws[col].v;
}
}
console.log(header);
const headerMustHave = ["Exam Name", "EId", "Name"];
const checker = (arr, target) => target.every((v) => arr.includes(v));
let ifFound = checker(header, headerMustHave);
if (ifFound === true) {
for (var i = 0; i < data.length; i++) {
let excel_date = ExcelDateToJSDate(data[i]["Report Date"]);
data[i]["Report Date"] = excel_date;
}
}
return { ws, data };
}
/**
* Read a DOM File into a binary string or array buffer; returns a Promise.
*/
function readFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
let type;
if (reader.readAsBinaryString) {
reader.readAsBinaryString(file);
type = "binaryString";
} else {
reader.readAsArrayBuffer(file);
type = "arrayBuffer";
}
reader.onload = (event) => {
resolve({ type, data: event.target.result });
};
reader.onerror = (event) => reject(event);
});
}
async function processExamInputFile(file) {
if (!file) {
throw new Error("No file selected.");
}
if (
!(
file.type === "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ||
file.name.endsWith(".xlsx")
)
) {
throw new Error("Invalid file type or extension.");
}
const { data, type } = await readFile(file);
const wb = XLSX.read(data, {
type: type === "binaryString" ? "binary" : "array",
bookVBA: true,
});
return processWorkbook(wb);
}
class X {
async handleExamInputFile() {
try {
const { ws, data } = await processExamInputFile(this.state.file);
this.setState({
data: data,
result: JSON.stringify(data),
cols: make_cols(ws["!ref"]),
});
await post(
"http://localhost:8000/upload",
{ data },
{
headers: {
Accept: "*",
"Content-Type": "application/json",
"Allow-Control-Allow-Origin": "*",
},
},
);
} catch (err) {
console.log(err); // TODO: improve
}
}
}

Firebase upload multiple files and get status

I have a React form where the user can upload multiple files. These are stored in fileList
async function uploadFiles(id) {
try {
const meta = await storageUploadFile(fileList, id);
console.log(meta);
} catch (e) {
console.log(e);
}
}
This calls my helper function that uploads the files to Firebase
export const storageUploadFile = function(files, id) {
const user = firebase.auth().currentUser.uid;
return Promise.all(
files.map((file) => {
return storage.child(`designs/${user}/${id}/${file.name}`).put(file)
})
)
};
What I'd like is on calling uploadFiles, get the total filesize of all items, and then show the overall progress.
At the moment, my code is only returning the file status in an array on completion
[
{bytesTransferred: 485561, totalBytes: 485561, state: "success"},
{bytesTransferred: 656289, totalBytes: 656289, state: "success"}
]
This is the way i do it:
import Deferred from 'es6-deferred';
export const storageUploadFile = function(files, id) {
const user = firebase.auth().currentUser.uid;
// To track the remaining files
let itemsCount = files.length;
// To store our files refs
const thumbRef = [];
// Our main tasks
const tumbUploadTask = [];
// This will store our primses
const thumbCompleter = [];
for (let i = 0; i < files.length; i += 1) {
thumbRef[i] = storage.ref(`designs/${user}/${id}/${file.name}`);
tumbUploadTask[i] = thumbRef[i].put(files[i]);
thumbCompleter[i] = new Deferred();
tumbUploadTask[i].on('state_changed',
(snap) => {
// Here you can check the progress
console.log(i, (snap.bytesTransferred / snap.totalBytes) * 100);
},
(error) => {
thumbCompleter[i].reject(error);
}, () => {
const url = tumbUploadTask[i].snapshot.metadata.downloadURLs[0];
itemsCount -= 1;
console.log(`Items left: ${itemsCount}`)
thumbCompleter[i].resolve(url);
});
}
return Promise.all(thumbCompleter).then((urls) => {
// Here we can see our files urls
console.log(urls);
});
};
Hope it helps.

How to upload file.mp3 to firebase storage in ionic?

I am creating an audio recording function in my ionic app. I am using media plugin:
$ ionic cordova plugin add cordova-plugin-media
$ npm install --save #ionic-native/media
I can record the audio and play it successfully like this:
constructor(private media: Media,private base64: Base64) {
this.file = this.media.create('file.mp3');
}
record_audio(){
this.file.startRecord();
}
to uplaod to firebase I cannot directly upload the file.mp3, looks like I need to convert it to Blob or base64 first so I tried doing this but it says "MediaObject cannot be assigned to string":
let filePath: string = 'this.file.mp3';
this.base64.encodeFile(filePath).then((base64File: string) => {
console.log(base64File);
}, (err) => {
console.log(err);
});
The objective is to upload the recorded audio file to firebase. to do that I need to convert this file.mp3 to base64.
startRecording() {
console.log("Started Recording");
this.recording = true;
this.file.createFile(this.file.tempDirectory, 'my_file.m4a', true).then(() => {
const audio: MediaObject = this.media.create(this.file.tempDirectory.replace(/^file:\/\//, '') + 'my_file.m4a');
console.log("Audio assigned to constant audio media object");
console.log(audio);
this.audio = audio;
console.log("Audio assigned to this.audio media object");
console.log(this.audio);
this.audio.startRecord();
this.listenToAudioEvents();
window.setTimeout(() => {
if (this.recording) this.stopRecording();
}, 10000);
});
}
listenToAudioEvents() {
this.audio.onStatusUpdate.subscribe(status => {
console.log("Status of this.audio updated");
console.log(status);
if (status == 4 && this.playingAudio) {
console.log("Time to stop playback")
this.stopPlayback();
}
});
}
stopRecording() {
this.audio.stopRecord();
console.log("Stopped Recording");
console.log(this.audio);
this.recording = false;
this.audioReady = true;
this.audio.getDuration();
console.log("Audio Duration: " + this.duration);
console.log("Audio Duration Property: " + this.audio.duration);
}
playAudio() {
console.log("Playing Audio");
this.playingAudio = true;
this.audio.play();
}
stopPlayback() {
console.log("Stopping Playback");
this.playingAudio = false;
this.audio.stop();
}
uploadAudio() {
console.log("Uploading record");
this.storeRecord().subscribe((downloadURL) => {
console.log("Finished storing record");
console.log("Download URL is " + downloadURL);
this.audioURL = downloadURL;
this.audioURLReady = true;
});
}
storeRecord() {
return Observable.create((observer) => {
console.log('Saving record');
const filePath = `${this.file.tempDirectory}my_file.m4a`;
console.log("Path to record is " + filePath);
const readFile: any = window['resolveLocalFileSystemURL'];
return readFile(filePath, (fileEntry) => {
return fileEntry.file((file) => {
const fileReader = new FileReader();
fileReader.onloadend = (result: any) => {
let arrayBuffer = result.target.result;
let blob = new Blob([new Uint8Array(arrayBuffer)], { type: 'audio/m4a' });
console.log("Blob is ");
console.log(blob);
var storageRef = firebase.storage().ref('content/' + this.firebase.user.uid + '/my-file.m4a');
console.log("Storage reference is " + storageRef);
var uploadTask = storageRef.put(blob);
console.log('Upload started:');
uploadTask.on('state_changed', (snapshot) => {
console.log("state changed");
let percent = uploadTask.snapshot.bytesTransferred / uploadTask.snapshot.totalBytes * 100;
console.log(percent + "% done");
}, (e) => {
console.error(e);
observer.error(e);
}, () => {
var downloadURL = uploadTask.snapshot.downloadURL;
console.log('Storage Download URL:' + downloadURL);
observer.next(downloadURL);
});
};
fileReader.onerror = (e: any) => {
console.error(e);
observer.error(e);
};
fileReader.readAsArrayBuffer(file);
}, (e) => {
console.error(e);
observer.error(e);
});
}, (e) => {
console.error(e);
observer.error(e);
});
});
}
downloadAudio() {
console.log("Downloading Audio")
const fileTransfer: FileTransferObject = this.fileTransfer.create();
var destPath = (cordova.file.externalDataDirectory || cordova.file.dataDirectory) + "my_file.m4a"
fileTransfer.download(this.audioURL, destPath, ).then((entry) => {
let rawAudioURI = entry.toURL();
this.audioURI = rawAudioURI.replace(/^file:\/\//, '/private');
this.audioURIReady = true;
console.log("Audio URI: " + this.audioURI);
}, (error) => {
console.error(error);
});
}
playAudioURI() {
console.log("Playing AudioURI");
let downloadedAudio: MediaObject = this.media.create(this.audioURI);
console.log("Downloaded audio: " + downloadedAudio);
downloadedAudio.play();
}
}

Resources