Получить изображение или байтовые данные с помощью http

Для веб-приложения мне нужно получать изображения с помощью ajax-запроса, потому что у нас есть подпись + аутентификация в нашем API, поэтому мы не можем получить изображения с помощью простого <img src="myapi/example/145"/>

Поскольку мы используем angular2, мы, очевидно, искали блоб или что-то в этом роде, но, как указано в файле static_response.d.ts:

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

Так что ладно, я пока не могу этого сделать, мне нужно дождаться реализации этой функции.

Но проблема в том, что я не могу ждать, поэтому мне нужно исправление или небольшой хак, чтобы получить данные изображения из ответа, и я смогу удалить свой хак и настроить вызов метода 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();
            } );
    }

Но я не получаю от него никакого изображения, и регистрация данных ответа показывает большую строку, которая является данными изображения.

У вас есть хак для этого?


person Supamiu    schedule 22.03.2016    source источник


Ответы (4)


Больше нет необходимости расширять BrowserXhr. (Проверено с помощью angular 2.2.1) RequestOptionsArgs теперь имеет свойство responseType: ResponseContentType, которому можно задать значение ResponseContentType.Blob.

Использование DomSanitizer

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

В этом примере также создается очищенный 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));
        })
person tschuege    schedule 29.11.2016
comment
Сегодня вы можете использовать res => res.blob(). - person ; 18.06.2017
comment
В более новых версиях Angular используйте headers: new HttpHeaders().append('Content-Type', 'image/jpg') - person Avram Cosmin; 13.09.2017

Этого очень легко добиться с помощью нового 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.

person Cuzox    schedule 29.10.2017
comment
Работает отлично! Спасибо - person Yossi Neiman; 09.11.2017

Я думаю, что вы пропустили установку responseType по вашему запросу. Сейчас это немного сложно, потому что это не поддерживается.

Обходным путем было бы переопределить класс BrowserXhr, чтобы установить responseType на самом объекте xhr...

Вы можете расширить 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 затронутого компонента...

Вот рабочий планкр: https://plnkr.co/edit/tC8xD16zwZ1UoEojebkm?p=preview.

person Thierry Templier    schedule 22.03.2016
comment
Итак, у меня было бы два http-провайдера, один для байтовых запросов и один для json? - person Supamiu; 22.03.2016
comment
Да, по умолчанию для запросов, которые возвращают json, и настраиваемый для тех, которые возвращают двоичные файлы... - person Thierry Templier; 22.03.2016
comment
Я добавил ссылку на plunkr в свой ответ - person Thierry Templier; 22.03.2016
comment
@ThierryTemplier Эй, этот плунжер больше не работает. Можете ли вы обновить его или обновить код здесь? Спасибо. - person Ng2-Fun; 07.03.2017

Этот JSFiddle может вам помочь: https://jsfiddle.net/virginieLGB/yy7Zs/936/

Метод, как вы хотели, создает BLOB-объект из предоставленного URL-адреса.

// 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();
person VirginieLGB    schedule 22.03.2016
comment
Проблема в том, что это полное решение JS, мне нужен хак TS, который может быть достигнут с помощью объекта Response, чтобы его было легко удалить, когда функция blob() будет доступна. - person Supamiu; 22.03.2016