不显示来自后端的图像

Posted

技术标签:

【中文标题】不显示来自后端的图像【英文标题】:Images from backend are not displayed 【发布时间】:2021-10-26 13:33:10 【问题描述】:

我从 Nestjs 后端传输到 Angular 前端的图像没有出现在浏览器中。

我从前端向后端发送一个查询,其中包含服务器上文件的路径(例如:“C:\MyFolder\MyFile.png”),它将读取图像并将流发送回前端。然后前端会将 blob 转换为图像,并将 img 元素的 src 属性设置为图像的 URL。

后端

控制器的后端代码:

@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"   >
    </mat-list-option>
  </mat-selection-list>
</div>

我做错了吗?有什么遗漏吗?

编辑:

感谢接受的答案的解决方案

首先需要将nestjs版本升级到v8+:nest update --force。不幸的是,我的项目失败了,所以我删除了 dist、node_modules 和 package-lock.json,使用 CLI v8+ 创建了一个新的 nestjs 项目,并使用生成的 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);

官方资源:https://docs.nestjs.com/techniques/streaming-files

【问题讨论】:

【参考方案1】:

如果你要返回一个流,你需要做类似的事情

@HttpCode(201)
@Get(':imageUrl')
@Header('Content-Type', 'image/png')
getFile(@Param('imageUrl')imageUrl: string, @Res() res: e.Response) 
    imageUrl = atob(imageUrl);
    return fs.createReadStream(imageUrl).pipe(res);

如果您使用的是 Nest v8,则可以使用 StreamableFile 并执行类似的操作

@HttpCode(201)
@Get(':imageUrl')
@Header('Content-Type', 'image/png')
getFile(@Param('imageUrl')imageUrl: string, @Res() res: e.Response) 
    imageUrl = atob(imageUrl);
    return new StreamableFile(fs.createReadStream(imageUrl));

Nest 会在后台为您调用.pipe(res)

【讨论】:

你太棒了,谢谢!我将在文章末尾包含最终的控制器代码。将nestjs升级到v8有点棘手,因为自动升级失败,所以我编辑了package.json,以一个新的nestjs应用v8为模型。看来您的 sn-ps 在“res”参数“e”上有一个小错字。不存在。 e 是我在import * as e from 'express' 中用作express 的别名,因此您可以将其键入为e.Response。只是有助于最大限度地减少变量碰撞

以上是关于不显示来自后端的图像的主要内容,如果未能解决你的问题,请参考以下文章

来自服务器端的数据不显示[重复]

当收到新消息而不重新加载视图时,如何将来自 stomp 客户端的消息显示到视图中

UITableView 不显示来自 URL 的图像 [重复]

UIImageView 不显示来自 UITableViewController 的设置图像

来自 S3 的 URL 图像不显示图像

图像不显示从数据库 Codeigniter 4