Angular 2 encode image to base64
So I find the solution:
compontent.ts
changeListener($event) : void { this.readThis($event.target);}readThis(inputValue: any): void { var file:File = inputValue.files[0]; var myReader:FileReader = new FileReader(); myReader.onloadend = (e) => { this.image = myReader.result; } myReader.readAsDataURL(file);}
component.html
<input type="file" accept="image/*" (change)="changeListener($event)">
Here is the answer above wrapped in a reuseable component that ties into ngmodel.
import { NgModule, Component, Input, Output, ElementRef, forwardRef } from '@angular/core';import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';import { FormsModule } from "@angular/forms";@Component({ selector: 'file-upload', template: `<input *ngIf="showFileNameInput" id="uploadFile" class="upload-file form-control" placeholder="Choose File" [(ngModel)]="selectedFileName" disabled="disabled" /> <div class="fileUpload btn btn-primary"> <span>{{uploadButtonText}}</span> <input type="file" class="upload" accept="*" (change)="changeListener($event)"> </div>`, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => FileUploadComponent), multi: true } ]})export class FileUploadComponent implements ControlValueAccessor { selectedFileName: string = null; @Input() showFileNameInput: boolean; @Input() uploadButtonText: string; writeValue(value: any) { //Handle write value } propagateChange = (_: any) => { }; registerOnChange(fn) { this.propagateChange = fn; } registerOnTouched() { } changeListener($event): void { // debugger; // uncomment this for debugging purposes this.readThis($event.target); } readThis(inputValue: any): void { // debugger; // uncomment this for debugging purposes var file: File = inputValue.files[0]; var myReader: FileReader = new FileReader(); myReader.onloadend = (e) => { this.propagateChange(myReader.result); this.selectedFileName = file.name; } myReader.readAsDataURL(file); }}@NgModule({ declarations: [ FileUploadComponent ], imports: [FormsModule], exports: [ FileUploadComponent ]})export class FileUploadModule { }
Which can be used like
<file-upload [showFileNameInput]="true" allowedTypes="image/*" uploadButtonText="Upload File" [(ngModel)]="someProperty"></file-upload>
Also some css that helped it blend into bootstrap on my site
/********************************//* File Upload */.fileUpload { position: relative; overflow: hidden;}.fileUpload input.upload { position: absolute; top: 0; right: 0; margin: 0; padding: 0; font-size: 20px; cursor: pointer; opacity: 0; filter: alpha(opacity=0);}.upload-file { &.form-control { width: auto; display: inherit; }}
You can create a Wrapper class for the FileReader class to return an observable.Subscribe for it and on success use the .target to get the base64 for do whatever you want.
import {ReplaySubject} from "rxjs/ReplaySubject";import {Observable} from "rxjs/Observable";export class ObservableFileReader { constructor(){} public readFile(fileToRead: File): Observable<MSBaseReader>{ let base64Observable = new ReplaySubject<MSBaseReader>(1); let fileReader = new FileReader(); fileReader.onload = event => { base64Observable.next(fileReader.result); }; fileReader.readAsDataURL(fileToRead); return base64Observable; }}