Hey guys, I got something working, so I thought I would share what I did. Given that this might not work for all cases, but it should be able to get you started.
First, I start the process off in a service I call CameraService (now called providers). This is a fully functional version, so there is a significant amount of side cases I handle here.
import { Injectable } from '@angular/core';
import { Platform } from 'ionic-angular';
import { Camera } from 'ionic-native';
import { StorageService } from './storage.service';
import { AuthService } from './auth.service';
declare var window: any;
@Injectable()
export class CameraService {
// Ability to upload videos
public options: any = {
sourceType: Camera.PictureSourceType.SAVEDPHOTOALBUM,
mediaType: Camera.MediaType.ALLMEDIA,
destinationType: Camera.DestinationType.FILE_URI
}
constructor(public platform: Platform,
public storage: StorageService,
public auth: AuthService) {}
getMedia(): Promise<any> {
return new Promise((resolve, reject) => {
Camera.getPicture(this.options).then( (fileUri: any) => {
console.log('File URI: ' + JSON.stringify(fileUri));
window.resolveLocalFileSystemURL('file://' + fileUri, (fileEntry) => {
console.log('Type: ' + (typeof fileEntry));
fileEntry.file( (file) => {
console.log('File: ' + (typeof file) + ', ' + JSON.stringify(file));
const fileReader = new FileReader();
fileReader.onloadend = (result: any) => {
console.log('File Reader Result: ' + JSON.stringify(result));
let arrayBuffer = result.target.result;
let blob = new Blob([new Uint8Array(arrayBuffer)], {type: 'video/mp4'});
const name = '' + Date.now() + this.auth.id;
this.upload(blob, name , file.type, resolve, reject);
};
fileReader.onerror = (error: any) => {
reject(error);
};
fileReader.readAsArrayBuffer(file);
}, (error) => {
console.log('File Entry Error: ' + JSON.stringify(error));
});
}, (error) => {
console.log('Error resolving file: ' + JSON.stringify(error));
});
});
});
}
upload(blob: Blob, name: string, type: string, resolve: any, reject: any) {
let uploadTask = this.storage.addBlob( name , type, blob);
uploadTask.on('state_changed' , (snapshot) => {
// Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
switch (snapshot.state) {
case firebase.storage.TaskState.PAUSED: // or 'paused'
console.log('Upload is paused');
break;
case firebase.storage.TaskState.RUNNING: // or 'running'
console.log('Upload is running');
break;
}
}, (error: any) => {
console.log('An Error has occured');
switch (error.code) {
case 'storage/unauthorized':
// User doesn't have permission to access the object
console.log('Unauthorized Access: ' + JSON.stringify(error));
reject(error.code);
break;
case 'storage/canceled':
// User canceled the upload
console.log('Canceled');
reject(error.code);
break;
case 'storage/unknown':
// Unknown error occurred, inspect error.serverResponse
console.log('Storage Unkown: ' + JSON.stringify(error));
reject(error.code);
break;
default:
console.log('Default: ' + JSON.stringify(error));
reject(error.code);
break;
}
}, () => {
console.log('Finished Uploading');
resolve( {url: uploadTask.snapshot.downloadURL, name: name, mediaType: type} );
});
}
}
This allows me to return a promise, and I should walk threw a lot of this code as it gets pretty complicated. First, I use non-nativeās camera plugin and their getPicture method. this will return me with a file URI, which on android looks something like
/storage/emulated/0/Movies/Instagram/VID_20880804_030651.mp4
Then, I need to convert this into a FileEntry object. Refer to Mozillaās FileEntry object. To do this I need the function listed above
window.resolveLocalFileSystemURL( url , function() )
If you noticed I had to add file:// to the URL I got earlier, that was android specific, and I havenāt fully tested this on IOS. Then I need a file entry file, which unfortunately for me does not convert the object into a javascript file object (or else I could use firebaseās storage to automatically put it up). Instead, I need to use FileReader to read the object into memory, and then on completion, create a Blob to upload to firebase.
The last and most important line of code here was
this.upload(blob, name, type)
But that just references another service that does a native firebase call
firebase.storage().ref().child('videos').child(name).put(blob)
That returns an URL, which I use in my promise resolution.
I know this is quite complicated, so feel free to ask questions. Thought I would share and help anyone out that I could.
Edit: Be sure to add the cordova file plugin to your app. Without this, the window.resolvelocalfilesystemURL call will probably fail.