Получить изображение или байтовые данные с http
Для веб-приложения мне нужно получить мои изображения с помощью запроса ajax, потому что у нас есть подпись + аутентификация в нашем API, поэтому мы не можем получить изображения с помощью простого <img src="myapi/example/145"/>
Поскольку мы используем angular2, мы явно искали blob или что-то в этом роде, но, как указано в 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();
} );
}
Но я не получаю никакого изображения от него, и регистрация данных ответа показывает большую строку, которая является данными изображения.
У вас есть хак для достижения этой цели?
4 ответа
Не надо расширять BrowserXhr
больше. (Протестировано с угловым 2.2.1) У RequestOptionsArgs теперь есть свойство responseType: ResponseContentType
который может быть установлен на ResponseContentType.Blob
Использование DomSanitizer
import {DomSanitizer} from '@angular/platform-browser';
В этом примере также создается очищенная ссылка, которая может быть связана с 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));
})
Используя новый Angular HttpClient действительно легко добиться этого. Исходя из подхода Чуеге, это будет:
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
Я думаю, что вы пропустили, чтобы установить 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.
Этот 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();