16

对于 Web 应用程序,我需要使用 ajax 请求获取图像,因为我们的 API 上有签名 + 身份验证,因此我们无法使用简单的获取图像<img src="myapi/example/145"/>

由于我们使用的是 angular2,我们显然在寻找 blob 或类似的东西,但正如static_response.d.ts文件中所述:

/**
 * Not yet implemented
 */
blob(): any;

所以好吧,我现在做不到,我必须等待这个功能被实现。

但问题是我等不及了,所以我需要一个修补程序或一些小技巧才能从响应中获取图像数据,我将能够删除我的 hack 并将blob()方法调用设置为在实现时良好。

我试过这个:

export class AppComponent {
    constructor(private api:ApiService, private logger:Logger){}
    title = 'Tests api';
    src='http://placekitten.com/500/200'; //this is src attribute of my test image
    onClick(){ //Called when I click on "test" button
        this.api.test().then(res => {
            console.log(res._body);
            var blob = new Blob([new Uint8Array(res._body)],{
                type: res.headers.get("Content-Type")
            });
            var urlCreator = window.URL;
            this.src = urlCreator.createObjectURL(blob);
        });
    }
}

ApiService.test()方法:

test():Promise<any> {
        return this.http.get(this._baseUrl + "myapi/example/145", this.getOptions())
//getOptions() is just creating three custom headers for     
//authentication and CSRF protection using signature
            .toPromise()
            .then(res => {
                    this.logger.debug(res);
                if(res.headers.get("Content-Type").startsWith("image/")){
                    return res;
                }
                return res.json();
            })
            .catch(res => {
                this.logger.error(res);
                return res.json();
            } );
    }

但是我没有从中得到任何图像,并且记录响应数据会显示一个大字符串,即图像数据。

你有办法实现这一点吗?

4

4 回答 4

27

没有必要再延长BrowserXhr了。(使用 Angular 2.2.1 测试) RequestOptionsArgs现在有一个responseType: ResponseContentType可以设置为的属性ResponseContentType.Blob

使用 DomSanitizer

import {DomSanitizer} from '@angular/platform-browser';

此示例还创建了一个经过净化的 url,该 url 可以绑定src<img>

this.http.get(url,  {
                        headers: {'Content-Type': 'image/jpg'},
                        responseType: ResponseContentType.Blob
                    })
        .map(res => {
            return new Blob([res._body], {
                type: res.headers.get("Content-Type")
            });
        })
        .map(blob => {
            var urlCreator = window.URL;
            return  this.sanitizer.bypassSecurityTrustUrl(urlCreator.createObjectURL(blob));
        })
于 2016-11-29T09:59:13.300 回答
11

使用新的 Angular HttpClient 很容易实现这一点。脱离tschuege的方法,它将是:

return this._http.get('/api/images/' + _id, {responseType: 'blob'}).map(blob => {
  var urlCreator = window.URL;
  return this._sanitizer.bypassSecurityTrustUrl(urlCreator.createObjectURL(blob));
})

关键是将 responseType 设置为“blob”,这样它就不会尝试将其解析为 JSON

于 2017-10-29T15:47:47.500 回答
4

我认为您错过了responseType按您的要求设置。现在它有点棘手,因为它不受支持。

解决方法是覆盖BrowserXhr类以responseTypexhr对象本身上设置...

您可以扩展BrowserXhr

@Injectable()
export class CustomBrowserXhr extends BrowserXhr {
  constructor() {}
  build(): any {
    let xhr = super.build();
    xhr.responseType = 'arraybuffer';
    return <any>(xhr);
  }
}

BrowserXhr并使用扩展类覆盖提供者:

bootstrap(AppComponent, [
  HTTP_PROVIDERS,
  provide(BrowserXhr, { useClass: CustomBrowserXhr })
]);

问题出在您没有覆盖所有请求。在引导级别,它将覆盖所有内容。providers因此,您可以在受影响组件的属性内的子注入器中提供它...

这是一个有效的 plunkr:https ://plnkr.co/edit/tC8xD16zwZ1UoEojebkm?p=preview 。

于 2016-03-22T12:43:58.310 回答
-1

这个 JSFiddle 可以帮助你: https ://jsfiddle.net/virginieLGB/yy7Zs/936/

如您所愿,该方法是从提供的 URL 创建一个 Blob

// Image returned should be an ArrayBuffer.
var xhr = new XMLHttpRequest();

xhr.open( "GET", "https://placekitten.com/500/200", true );

// Ask for the result as an ArrayBuffer.
xhr.responseType = "arraybuffer";

xhr.onload = function( e ) {
    // Obtain a blob: URL for the image data.
    var arrayBufferView = new Uint8Array( this.response );
    var blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } );
    var urlCreator = window.URL || window.webkitURL;
    var imageUrl = urlCreator.createObjectURL( blob );
    var img = document.querySelector( "#photo" );
    img.src = imageUrl;
};

xhr.send();
于 2016-03-22T11:43:33.737 回答