【问题标题】:Get Image or byte data with http使用 http 获取图像或字节数据
【发布时间】:2018-03-17 02:13:47
【问题描述】:

对于 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();
            } );
    }

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

你有办法实现这一点吗?

【问题讨论】:

    标签: javascript angular angular2-http


    【解决方案1】:

    不再需要扩展BrowserXhr。 (使用角度 2.2.1 测试) RequestOptionsArgs 现在有一个属性responseType: ResponseContentType 可以设置为ResponseContentType.Blob

    使用 DomSanitizer

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

    此示例还创建了一个可绑定到 &lt;img&gt;src 属性的净化 url

    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));
            })
    

    【讨论】:

    • 今天你可以使用res =&gt; res.blob()
    • 在较新版本的 Angular 中使用 headers: new HttpHeaders().append('Content-Type', 'image/jpg')
    【解决方案2】:

    使用新的 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

    【讨论】:

    • 效果很好!谢谢
    【解决方案3】:

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

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

    你可以扩展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

    【讨论】:

    • 所以我会有两个 http 提供者,一个用于字节请求,一个用于 json 请求?
    • 是的,对于返回 json 的请求的默认请求和返回二进制请求的自定义请求...
    • 我在答案中添加了一个 plunkr 链接
    • @ThierryTemplier 嘿,这个 plunker 不再工作了。您可以在这里更新它或更新代码吗?谢谢。
    【解决方案4】:

    这个 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();
    

    【讨论】:

    • 问题是这是一个完整的 JS 解决方案,我需要一个可以通过 Response 对象实现的 TS hack,以便在 blob() 函数可用时轻松删除。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-12
    • 2019-04-23
    • 2012-06-09
    • 1970-01-01
    • 2014-11-14
    相关资源
    最近更新 更多