NestJS后端传输至Angular前端的图片无法在浏览器显示如何解决?
问题描述
从NestJS后端向Angular前端传输图片时,图片无法在浏览器中正常展示。
实现逻辑为:前端向后端发送携带服务器文件路径(例如:C:\MyFolder\MyFile.png)的请求,后端读取对应图片后返回流给前端,前端将Blob转换为图片资源后,赋值给img元素的src属性完成渲染。
原有代码实现
后端控制器代码
@HttpCode(201) @Get(':imageUrl') @Header('Content-Type', 'image/png') getFile(@Param('imageUrl')imageUrl: string) { imageUrl = atob(imageUrl); return fs.createReadStream(imageUrl); }
前端代码
语言选择器TS代码
currentLanguage: ApplicationLanguage; availableLanguages: ApplicationLanguage[]; constructor(private readonly _languageProvider: CultureProviderService, private readonly _imageLoader: ImageService) { this.currentLanguage = _languageProvider._currentLanguage; _languageProvider.languageChanged.subscribe( newLanguage => { this.currentLanguage = newLanguage; } ) } ngOnInit(): void { this._languageProvider.getAllAvailableLanguages().subscribe( (languages: ApplicationLanguage[]) => { this.availableLanguages = languages; languages.forEach((language: ApplicationLanguage) => { this._imageLoader.getImage(language.flagIcon).subscribe( imgBlob => { this._imageLoader.createImageFromBlob(imgBlob).then( result => { language.image = result; }, err => { console.log(err); } ) } ); }); }, err => { console.log(err); } ); }
图片加载服务代码
constructor(private readonly _http: HttpClient, private domSanitizer: DomSanitizer) { } getImage(imageUrl: string): Observable<Blob> { return this._http.get(`${environment.machineServerUrl}/file/${btoa(imageUrl)}`, { responseType: 'blob' }); } createImageFromBlob(imageUrl: Blob): Promise<SafeUrl> { return new Promise<SafeUrl>((resolve, reject) => { const reader = new FileReader(); reader.addEventListener( "load", () => { resolve(this.domSanitizer.bypassSecurityTrustUrl(reader.result as string)); } ); if (imageUrl) { reader.readAsDataURL(imageUrl); } else { reject(); } }); }
HTML代码
<div> <mat-selection-list (selectionChange)="changeLanguage($event)" [multiple]="false"> <mat-list-option *ngFor="let language of availableLanguages" [value]="language" [selected] ="isSelected(language)"> <img [src]="language.image" height="70px" width="70px" alt="国旗"> </mat-list-option> </mat-selection-list> </div>
解决方案
问题出在低版本NestJS无法直接正确处理返回的文件流,需按以下步骤修改:
- 升级NestJS版本至v8及以上,执行命令:
nest update --force。如果升级失败,可以删除dist、node_modules和package-lock.json文件,用v8以上版本的NestJS CLI新建项目,用新生成的package.json覆盖原有项目的对应文件完成升级。 - 修改后端控制器代码,使用StreamableFile包装返回的文件流:
@HttpCode(201) @Get(':imageUrl') @Header('Content-Type', 'image/png') getFile(@Param('imageUrl')imageUrl: string): StreamableFile { imageUrl = Buffer.from(imageUrl, 'base64').toString(); const file = createReadStream(imageUrl); return new StreamableFile(file); }
内容的提问来源于stack exchange,提问作者nkoniishvt
相关产品推荐
相关产品推荐

