【问题标题】:Angular base64 image pipe, Maximum call stack size exceeded角度 base64 图像管道,超出最大调用堆栈大小
【发布时间】:2017-11-22 18:28:30
【问题描述】:

我必须将图片网址转换为 base64 编码字符串(因为 this

import { Pipe, PipeTransform } from '@angular/core';


declare var base64;

@Pipe({
  name: 'tobase64'
})
export class Tobase64Pipe implements PipeTransform {

  transform(value: any, args?: any): any {
    var xmlHTTP = new XMLHttpRequest();
    xmlHTTP.open('GET', value, true);
    xmlHTTP.responseType = 'arraybuffer';
    xmlHTTP.onload = (e) => {
        console.log('e',e);
      var arr = new Uint8Array(e.currentTarget.response);
      var raw = String.fromCharCode.apply(null, arr);
      var b64 = base64.encode(raw);
       var dataURL = "data:image/png;base64," + b64;
      return dataURL;
    };
    xmlHTTP.send();

    return null;
  }

}

HTML

<image x="0" y="0" width="500" height="500" [attr.xlink:href]="'assets/hand.jpg' | tobase64"    mask="url(#hole)" />  

错误:

ERROR RangeError: Maximum call stack size exceeded

【问题讨论】:

  • 检查这个stackoverflow.com/questions/9267899/… 它看起来可能会有所帮助 - 您可能需要包含一个 for 循环。问题也可能重复。
  • ouch,一个进行 Http 调用的管道。我不认为这是个好主意。每次对作用域组件进行一些更改时,管道都会重新运行。这就是您收到此错误的原因。只需检查您的请求,它会溢出 http 堆栈。
  • 更不用说 .apply() 它将为每个 charCode 执行一个函数,对于 base64 编码的图像来说将不止几个。

标签: javascript angular


【解决方案1】:

从管道执行 HTTP 请求是完全可以的。在你的情况下,你最终只会做一个。考虑一下:如果您将imgsrc 属性绑定到可以动态更改的属性,您最终将在属性更改时进行服务器调用;无论该调用是 XHR 调用还是对图像的简单请求,这并不是什么大问题。关于您的管道,我唯一不太了解的两件事如下:

  1. 为什么使用 XMLHTTPRequest 而不是 Angular 的 Http 或 HttpClient 服务?
  2. 为什么你的管道返回null?看来即使你没有得到任何错误,你仍然不会得到结果

此解决方案需要明确两个管道:一个是用于进行 XHR 调用的自定义管道,另一个是 Angular 的内置管道 async。这是我们的自定义管道:

import { Pipe, PipeTransform } from '@angular/core';
import { Http, RequestOptions, Headers, ResponseContentType } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';

@Pipe({name: 'toBase64'})
export class ImagePipe implements PipeTransform {
  constructor(private http: Http) {}

  transform(url: string) {
  const headers = new Headers({'Content-Type': 'image/*'}); /* tell that XHR is going to receive an image as response, so it can be then converted to blob */
  return this.http.get(url, new RequestOptions({headers: headers, responseType: ResponseContentType.Blob})) // specify that response should be treated as blob data
  .map(response => response.blob()) // take the blob
  .switchMap(blob => {
  // return new observable which emits a base64 string when blob is converted to base64
      return Observable.create(observer => { 
        const  reader = new FileReader(); 
        reader.readAsDataURL(blob); // convert blob to base64
        reader.onloadend = function() {             
              observer.next(reader.result); // emit the base64 string result
        }
     });
   });
  }
}

这是你的html:

<image x="0" y="0" width="500" height="500" [attr.xlink:href]="('assets/hand.jpg' | toBase64) | async"    mask="url(#hole)" /> 

我们使用管道获取 base64 字符串的 observable,并使用 async 将实际发出的字符串插入到 src 标记内。

您需要记住的一件事是 CORS:您的图像服务服务器应配置为接受来自运行 Angular 应用程序的域中的图像的 XHR 调用,此外,您还必须提供绝对 URL到自定义管道,否则它将向 Angular 应用程序的域本身发出请求。但在你的情况下,我假设你从自己的应用程序中提供图像,所以这不应该是一个真正的问题。

【讨论】:

    猜你喜欢
    • 2016-04-20
    • 2019-06-11
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-24
    • 2015-12-29
    相关资源
    最近更新 更多