Angular からドラッグでファイルをFunctionsにアップロードしてOCR

Angular からファイルを選択し、Cloud Functions 経由で Cloud Vision を呼び出して OCRの結果を表示するところまでの疎通確認ができた

あと、ドラッグでファイルを登録できるようにできれば、アプリに組み込むための素材はそろう感じ。

これまでの経緯。

  1. Functions試す
  2. Functions環境構築
  3. Firestore連携
  4. ファイルアップロード
  5. Cloud Vision連携
  6. Cloud Functions アプリ呼び出し
  7. AngularからBase64化したファイルでCloud Functiono呼び出しOCR

出来上がったデモは、こんな感じ。

1.手順

Angular用に、ドラッグ&ドロップをサポートした、ファイルアップロード パッケージはいくつかあった(ちょっと試してみたのは、ng2-file-upload)

しかしながら、ファイルのアップロード自体は、Base64でJSONにのっけて送ることにしたため、まぁファイルのアップロード自体の機能は不要。

なので、ファイルのドロップに特化した以下のパッケージを使用する。

2.ドロップパッケージのインストール

ngx-dropzone

npm install ng2-file-upload --save

3.実装

3.1 app.module.ts

抜粋

import { BrowserModule } from '@angular/platform-browser';
import { AngularFireModule } from '@angular/fire';
import { AngularFirestoreModule } from '@angular/fire/firestore';
import { AngularFireFunctionsModule, REGION } from '@angular/fire/functions';
import { NgxDropzoneModule } from 'ngx-dropzone';
   :

@NgModule({
  declarations: [
    AppComponent,
     :
  ],
  imports: [
    BrowserModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFirestoreModule,
    AngularFireFunctionsModule,
    NgxDropzoneModule,
     :
  ],
  providers: [
    { provide: REGION, useValue: 'us-central1' }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

3.2 Angular ページ

ngx-dropzoneのでもページを参考にしながら。

<h1>Fileupload</h1>
<div>
  <div style="padding:20px;">
    <textarea cols="60" rows="5" [(ngModel)]="ocrText"></textarea>
  </div>
    <div class="custom-dropzone" ngx-dropzone [accept]="'image/*'" (change)="onFileChanged($event)">
    <ngx-dropzone-label>
      <div>
        <h2>ファイルをドラッグするかクリックしてファイル選択</h2>
      </div>
    </ngx-dropzone-label>
    <ngx-dropzone-image-preview ngProjectAs="ngx-dropzone-preview" *ngFor="let f of files" [file]="f" [removable]="true" (removed)="onRemove(f)">
      <ngx-dropzone-label>{{ f.name }} ({{ f.type }})</ngx-dropzone-label>
    </ngx-dropzone-image-preview>
  </div>
  <button (click)="onUpload()">Upload!</button>
</div>

3.3 Angular CSS

ドロップゾーンのデザインをカスタマイズできる。
ngx-dropzone,
.custom-dropzone {
  margin: 20px;
}

.custom-dropzone {
	height: 140px;
	//background: #333;
	//color: #fff;
	border: 2px dashed rgb(235, 79, 79);
	border-radius: 8px;
	font-size: 12px;
}

.custom-dropzone.ngx-dz-hovered {
  border: 2px solid rgb(235, 79, 79);
}

3.4 Angular コンポーネント

基本的に、前回と同じ。選択されたファイルの取り扱いを少し変える。

import { Component, OnInit } from '@angular/core';
import { AngularFireFunctions } from '@angular/fire/functions';
import { Observable, from } from 'rxjs';

@Component({
  selector: 'app-management',
  templateUrl: './management.component.html',
  styleUrls: ['./management.component.scss']
})
export class ManagementComponent implements OnInit {
  addMessageCallable: any;
  visionsCallable: any;
  ocrText: string = "";
  files: File[] = [];

  constructor(private fns: AngularFireFunctions) { 
    this.visionsCallable = fns.httpsCallable('sampleOnCallVisions');
  }

  ngOnInit(): void {
  }

  onFileChanged(event) {
    console.log(event);
    this.files.push(...event.addedFiles);
  }

  onRemove(event) {
    console.log(event);
    this.files.splice(this.files.indexOf(event), 1);
  }

  async onUpload() {
    const reader = new FileReader();
    const promise = new Promise(function(resolve, reject){
      reader.onload = (function(){
          return function(e){
            // data:text/plain;base64,xxxxx
            var fileBase64 = e.target.result.split(',')[1];
            resolve(fileBase64);
          };
      })();
    });
    
    const selectedFile = this.files[0];
    console.log(selectedFile);
    
    reader.readAsDataURL(selectedFile);
    const fileBase64 = await promise.then();
    console.log(fileBase64);

    const observer = this.visionsCallable(
      {
        filename: selectedFile.name,
        base64encodedFile: fileBase64
      }) as Observable<any>;

    try {
      const res = await observer.toPromise();
      this.ocrText = res.result;
    } catch(e) {
      console.log(e);
    }
  }
}

3.5 Functions

こちらは完全に、前回と同じ。

https://www.typea.info/blog/index.php/2020/08/11/angular-cloud-functions-ocr/

を参照。

ようやく、開発中のアプリに機能を組み込むことが出来そう!

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です