Angular一次性绑定图片属性源

Angular Binding a Image Attribute Source just for One-Time

只有一次,从 Observable 中 ngOnInit 触发,我收到一个 JSON 带有文本和图像的对象。

图片以数组的形式出现。 Text-Binding 效果很好,但图像的源属性绑定是一个杀手 - 图像的数据可以达到 1MB 甚至更多。

Text <h2>{{support.VehicleName}}</h2> 可以从另一个 Observable 改变,这部分效果很好。但我不需要更改图像。如何一次性绑定我的图像源?

HTML:

<div *ngFor="let support of IsSupportInOperation">
    <h2>{{support.VehicleName}}</h2>
    <img [src]='innerHtml(support.VehicleImage.data)' />
</div>`

打字稿:

import { Component, OnInit, OnDestroy, Input } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'
import { FireCrewService, ViewOnSupportInOperation } from '../shared/fire-crew.service';
import { DomSanitizer } from '@angular/platform-browser';


@Component({
    selector: 'app-display',
    templateUrl: './display.component.html',
    styleUrls: ['./display.component.css']
})

export class DisplayComponent implements OnInit {

@Input() OperationId: number = 0;

destroy$ = new Subject();
IsSupportInOperation = new Array<ViewOnSupportInOperation>();

observer = {
    next: (value: ViewOnSupportInOperation[]) => this.onNext(value),
    error: (err: string) => this.onError(err),
    complete: () => this.onComplete(),
};

constructor(private fs: FireCrewService,
    private sanitizer: DomSanitizer) {
}


ngOnDestroy(): void {
    this.destroy$.next();
}

ngOnInit(): void {
    this.fs.getAlarm(this.OperationId)
        .pipe(takeUntil(this.destroy$))
        .subscribe(this.observer);
}


onNext(value: ViewOnSupportInOperation[]): void
{
    this.IsSupportInOperation = [];

    value.forEach(element => {
        if (element.SrcId == element.DstId) {
            this.IsSupportInOperation.push(element);
        }
    });
}

onError(value: string): void {
}

onComplete(): void {
}


innerHtml(value: Buffer) {
    return this.sanitizer.bypassSecurityTrustUrl('data:image/jpeg;base64,' + this._arrayBufferToBase64(value));
}

_arrayBufferToBase64(value: Buffer) {
    var binary = '';
    var bytes = new Uint8Array(value);
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i]);
    }
    return window.btoa(binary);
}

}

SQL:

CREATE TABLE [dbo].[Vehicle]
(
    [Id] INT IDENTITY (1, 1) NOT NULL
    , [SrcId] INTEGER NOT NULL
    , [DstId] INTEGER NOT NULL
    , [VehicleName] NVARCHAR (32)   NOT NULL
    , [VehicleImage] VARBINARY(MAX) NULL
)

接口:

export interface ViewOnSupportInOperation {
    Id: number;
    SrcId: number;
    DstId: number;
    VehicleName: string;
    VehicleImage: any;
}

JSON:

[
    {
        "Id":1,
        "VehicleName":"Car",
        "VehicleImage": {
            "type":"Buffer",
            "data":[
                255,254,253, ...
            ]
        }
    }
]

API:

async function getAlarm(id) {
    try {
        let pool = await sql.connect(config);
        let query = await pool.request().query("SELECT * FROM Vehicle WHERE Id = " + id);
        return query.recordset;
    }
    catch (error) {
        console.error(error);
    }
}

我找到了解决方案,我用 MySafeUrl: SafeUrl 扩展了我的 ViewOnSupportInOperation 界面:

export interface ViewOnSupportInOperation {
    Id: number;
    SrcId: number;
    DstId: number;
    VehicleName: string;
    VehicleImage: any;
    MySafeUrl: SafeUrl;
}

在我的 onNext 中,我计算了 SafeUrl element.MySafeUrl = this.innerHtml(element.VehicleImage.data);:

onNext(value: ViewOnSupportInOperation[]): void
{
    this.IsSupportInOperation = [];

    value.forEach(element => {

        element.MySafeUrl = this.innerHtml(element.VehicleImage.data);

        if (element.SrcId == element.DstId) {
            this.IsSupportInOperation.push(element);
        }

    });
}

HTML,更改为<img [src]=support.MySafeUrl />

<div *ngFor="let support of IsSupportInOperation">
    <h2>{{support.VehicleName}}</h2>
    <img [src]=support.MySafeUrl />
</div>`