Angular 16中如何通过带JWT授权的请求头加载图片?
Angular 16 用管道解决带JWT认证的图片加载问题
因为<img>标签的请求是浏览器直接发起的,不会经过Angular的HTTP拦截器,所以需要通过管道结合HttpClient手动添加认证头,再将图片转为安全的可访问URL。
1. 创建安全图片管道
首先生成管道:
ng generate pipe secure-image
然后修改secure-image.pipe.ts的代码:
import { Pipe, PipeTransform } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; import { Observable, map, catchError, of } from 'rxjs'; @Pipe({ name: 'secureImage', pure: false // 非纯管道,处理动态token或URL变化 }) export class SecureImagePipe implements PipeTransform { // 缓存已请求的图片,避免重复发起请求 private imageCache = new Map<string, Observable<SafeUrl>>(); constructor( private http: HttpClient, private sanitizer: DomSanitizer, // 若有AuthService,替换为注入服务获取token,更规范 // private authService: AuthService ) {} transform(imageUrl: string, defaultImageUrl = '/assets/default-image.png'): Observable<SafeUrl> { // 先检查缓存,存在则直接返回 if (this.imageCache.has(imageUrl)) { return this.imageCache.get(imageUrl)!; } // 获取JWT令牌,这里用localStorage示例,实际建议用AuthService const token = localStorage.getItem('authToken'); if (!token) { return of(this.sanitizer.bypassSecurityTrustUrl(defaultImageUrl)); } const headers = new HttpHeaders().set('Authorization', `Bearer ${token}`); const imageRequest$ = this.http.get(imageUrl, { headers, responseType: 'blob' }).pipe( map(blob => { // 将blob转为浏览器可识别的URL const objectUrl = URL.createObjectURL(blob); return this.sanitizer.bypassSecurityTrustUrl(objectUrl); }), catchError(() => { // 请求失败时返回默认图片 return of(this.sanitizer.bypassSecurityTrustUrl(defaultImageUrl)); }) ); // 存入缓存 this.imageCache.set(imageUrl, imageRequest$); return imageRequest$; } }
2. 在模板中使用管道
在需要加载认证图片的地方,用管道配合async管道处理Observable:
<!-- 替换为你的图片API地址 --> <img [src]="'/api/images/user-avatar' | secureImage | async" alt="用户头像"> <!-- 可自定义默认图片 --> <img [src]="'/api/images/product-photo' | secureImage:'/assets/no-image.png' | async" alt="产品图片">
3. 模块配置
确保在你的功能模块(或AppModule)中声明管道,并导入必要的模块:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http'; import { SecureImagePipe } from './secure-image.pipe'; @NgModule({ declarations: [ // ...其他组件/指令 SecureImagePipe ], imports: [ BrowserModule, HttpClientModule ] }) export class AppModule {}
关键注意事项
- 内存泄漏处理:
URL.createObjectURL会占用浏览器内存,若需要更严谨的清理,可以结合自定义指令在组件销毁时调用URL.revokeObjectURL()释放资源。 - Token获取方式:示例中用
localStorage直接取token,实际项目建议封装AuthService统一管理token的获取和刷新,避免硬编码。 - 非纯管道:设置
pure: false是为了处理token更新或URL动态变化的场景,若你的图片URL和token都不会动态改变,也可以设置为纯管道并优化缓存逻辑。 - 性能优化:缓存机制避免了重复请求同一图片,适合列表类多图片场景。
内容的提问来源于stack exchange,提问作者NIKE
相关产品推荐
相关产品推荐

