File 角度2将图像编码到base64

File 角度2将图像编码到base64,file,angular,typescript,base64,encode,File,Angular,Typescript,Base64,Encode,我想将上传的文件编码到base64,以便将它们传递给请求。问题是,我正在使用Angular 2和Typescript,但我找不到任何关于如何做到这一点的信息。我发现在Javascript中可以用canvas完成,但我不知道如何用Typescript实现代码 <input type="file" class="form-control" accept="image/*" multiple [(ngModel)]="spot.images" name="images"> 您可以

我想将上传的文件编码到base64,以便将它们传递给请求。问题是,我正在使用Angular 2和Typescript,但我找不到任何关于如何做到这一点的信息。我发现在Javascript中可以用canvas完成,但我不知道如何用Typescript实现代码

<input type="file" class="form-control" accept="image/*" multiple
    [(ngModel)]="spot.images" name="images">

您可以为FileReader类创建一个包装类,以返回一个可观察的。订阅它,成功后使用.target获取base64,以便执行任何您想要的操作

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;
   }
}
从“rxjs/ReplaySubject”导入{ReplaySubject};
从“rxjs/Observable”导入{Observable};
导出类ObservableFileReader{
构造函数(){}
公共读取文件(fileToRead:File):可观察{
设base64Observable=新的ReplaySubject(1);
让fileReader=newFileReader();
fileReader.onload=事件=>{
base64Observable.next(fileReader.result);
};
fileReader.readAsDataURL(fileToRead);
可观察的返回基线;
}
}

因此我找到了解决方案:

成分ts

component.html


以上答案被包装在与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 { }

使用Rxjs的可能解决方案

  import { fromEvent } from 'rxjs';
  import { pluck } from 'rxjs/operators';

   onUploadImage(event) {
    if (event.target.files.length > 0) {
      const fileReader = new FileReader();
      let imageToUpload = event.target.files.item(0);
      this.imageToBase64(fileReader, imageToUpload)
        .subscribe(base64image => {
          // do something with base64 image..
        });
    }
  }

  imageToBase64(fileReader: FileReader, fileToRead: File): Observable<string> {
    fileReader.readAsDataURL(fileToRead);
    return fromEvent(fileReader, 'load').pipe(pluck('currentTarget', 'result'));
  }
从'rxjs'导入{fromEvent};
从“rxjs/operators”导入{pull};
onUploadImage(事件){
如果(event.target.files.length>0){
const fileReader=new fileReader();
让imageToUpload=event.target.files.item(0);
this.imageToBase64(文件阅读器,imageToUpload)
.订阅(base64image=>{
//使用base64映像执行某些操作。。
});
}
}
imageToBase64(文件读取器:文件读取器,文件读取器:文件):可观察{
fileReader.readAsDataURL(fileToRead);
从事件(fileReader,'load').pipe(pull('currentTarget','result'))返回;
}

您不使用FileReader.readAsDataURL()的任何原因?有解决方案吗?我需要这个工作代码:你能添加一个代码片段吗?我不明白这里的意思,这很好用。我甚至能够将它封装在一个组件中,该组件与ngmodel绑定,将其用作表单控件。如果你感兴趣,请看我的答案。祝你愉快!多个文件怎么样?太棒了!我用您的解决方案创建了一个StackBlitz:我收到一个错误引用错误:e未定义您如何将其传递给请求?这里的base64值是什么?@mix64值被输出到绑定到组件的ngModel或formControl的任何对象。您可以这样使用它。基64字符串将位于组件的“someProperty”中。您的意思是
someProperty
是组件内部的变量吗?很抱歉,我对这一点很陌生。@是的,someProperty是组件中的一个变量。@Josh我在表单中使用它时遇到此错误,如果在表单标记中使用ngModel,则必须在ngModelOptions中设置name属性或将表单控件定义为“standalone”,如何在表单中使用它,以便可以在服务器上发布
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 { }
<file-upload [showFileNameInput]="true" allowedTypes="image/*" uploadButtonText="Upload File" [(ngModel)]="someProperty"></file-upload> 
/********************************/
/* 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;
    }
}
  import { fromEvent } from 'rxjs';
  import { pluck } from 'rxjs/operators';

   onUploadImage(event) {
    if (event.target.files.length > 0) {
      const fileReader = new FileReader();
      let imageToUpload = event.target.files.item(0);
      this.imageToBase64(fileReader, imageToUpload)
        .subscribe(base64image => {
          // do something with base64 image..
        });
    }
  }

  imageToBase64(fileReader: FileReader, fileToRead: File): Observable<string> {
    fileReader.readAsDataURL(fileToRead);
    return fromEvent(fileReader, 'load').pipe(pluck('currentTarget', 'result'));
  }