[firestore][js] implement Blob support

This commit is contained in:
Salakar 2018-05-03 20:13:51 +01:00
parent 5906d20ce0
commit 9c49d9ef57
5 changed files with 48 additions and 32 deletions

View File

@ -1,32 +1,40 @@
import Base64 from './utils/Base64';
type BlobFormat = 'string' | 'array';
export default class Blob {
_data: Uint8Array | string;
_type: BlobFormat;
_binaryString: string;
constructor(data, type: BlobFormat) {
this._data = data;
this._type = type;
constructor(binaryString) {
this._binaryString = binaryString;
}
/**
* Creates a new Blob from the given Base64 string
*
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#.fromBase64String
* @param base64 string
*/
static fromBase64String(base64: string): Blob {
return new Blob(base64, 'string');
return new Blob(Base64.atob(base64));
}
/**
* Creates a new Blob from the given Uint8Array.
*
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#.fromUint8Array
* @param array Array
*/
static fromUint8Array(array: Uint8Array): Blob {
return new Blob(array, 'array');
if (!(array instanceof Uint8Array)) {
throw new Error(
'firestore.Blob.fromUint8Array expects an instance of Uint8Array'
);
}
return new Blob(
Array.prototype.map
.call(array, (char: number) => String.fromCharCode(char))
.join('')
);
}
/**
@ -36,45 +44,42 @@ export default class Blob {
* @returns boolean 'true' if this Blob is equal to the provided one.
*/
isEqual(blob: Blob): boolean {
let thisBlobBase64 = '';
if (this._type === 'string') thisBlobBase64 = this._data;
else thisBlobBase64 = this.toBase64();
if (!(blob instanceof Blob)) {
throw new Error('firestore.Blob.isEqual expects an instance of Blob');
}
let thatBlobBase64 = '';
if (blob._type === 'string') thatBlobBase64 = blob._data;
else thatBlobBase64 = blob.toBase64();
return thisBlobBase64 === thatBlobBase64;
return this._binaryString === blob._binaryString;
}
/**
* Returns the bytes of a Blob as a Base64-encoded string.
*
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#toBase64
* @returns string The Base64-encoded string created from the Blob object.
*/
toBase64(): string {
if (this._type === 'string') return this._data;
let binary = '';
const len = this._data.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(this._data[i]);
}
return Base64.btoa(binary);
return Base64.btoa(this._binaryString);
}
/**
* Returns the bytes of a Blob in a new Uint8Array.
*
* @url https://firebase.google.com/docs/reference/js/firebase.firestore.Blob#toUint8Array
* @returns non-null Uint8Array The Uint8Array created from the Blob object.
*/
toUint8Array(): Uint8Array {
if (this._type === 'array') return this._data;
return new Uint8Array(
Base64.atob(this._data)
.split('')
.map(c => c.charCodeAt(0))
this._binaryString.split('').map(c => c.charCodeAt(0))
);
}
/**
* Returns a string representation of this blob instance
*
* @returns {string}
* @memberof Blob
*/
toString(): string {
return `firestore.Blob(base64: ${this.toBase64()})`;
}
}

View File

@ -11,6 +11,7 @@ import DocumentReference from './DocumentReference';
import FieldPath from './FieldPath';
import FieldValue from './FieldValue';
import GeoPoint from './GeoPoint';
import Blob from './Blob';
import Path from './Path';
import WriteBatch from './WriteBatch';
import TransactionHandler from './TransactionHandler';
@ -258,6 +259,7 @@ export const statics = {
FieldPath,
FieldValue,
GeoPoint,
Blob,
enableLogging(enabled: boolean): void {
// DEPRECATED: Remove method in v4.1.0
console.warn(

View File

@ -42,6 +42,7 @@ export type NativeTypeMap = {
| 'array'
| 'boolean'
| 'date'
| 'blob'
| 'documentid'
| 'fieldvalue'
| 'geopoint'

View File

@ -24,7 +24,7 @@ export default {
if (charCode > 0xff) {
throw new Error(
"'btoa' failed: The string to be encoded contains characters outside of the Latin1 range."
"'firestore.utils.btoa' failed: The string to be encoded contains characters outside of the Latin1 range."
);
}
@ -48,7 +48,7 @@ export default {
if (str.length % 4 === 1) {
throw new Error(
"'atob' failed: The string to be decoded is not correctly encoded."
"'firestore.utils.atob' failed: The string to be decoded is not correctly encoded."
);
}

View File

@ -3,6 +3,7 @@
*/
import DocumentReference from '../DocumentReference';
import Blob from '../Blob';
import { DOCUMENT_ID } from '../FieldPath';
import {
DELETE_FIELD_VALUE,
@ -98,6 +99,11 @@ export const buildTypeMap = (value: any): NativeTypeMap | null => {
type: 'date',
value: value.getTime(),
};
} else if (value instanceof Blob) {
return {
type: 'blob',
value: value.toBase64(),
};
}
return {
type: 'object',
@ -156,6 +162,8 @@ const parseTypeMap = (firestore: Firestore, typeMap: NativeTypeMap): any => {
return new GeoPoint(value.latitude, value.longitude);
} else if (type === 'date') {
return new Date(value);
} else if (type === 'blob') {
return Blob.fromBase64String(value);
}
console.warn(`Unknown data type received ${type}`);
return value;