Захват HTTP-перехватчика в динамическом запросе ngSrc

Я создал приложение AngularJS, которое загружает изображения из защищенного брандмауэра OAuth. Моя библиотека OAuth настроена путем добавления дополнительного перехватчика к Angular $httpProvider для добавления правильного заголовка проверки подлинности.

Мой исходный код в моем шаблоне HTML выглядит следующим образом:

<img ng-src="{{ '/users/1/images/' + imageId }}">

Моя проблема заключается в том, что HTTP-запрос, созданный директивой ngSrc, игнорируется реализацией $http, что приводит к запросу с неправильной аутентификацией. Нормальные функции API-вызовов функционируют корректно (те, которые вызываются моими контроллерами/службами, напрямую используя $http и $resource).

Ответ 1

Директива ngSrc просто управляет обычным атрибутом src для img, что заставляет браузер запрашивать изображение так же, как и любое другое изображение, а не через Javascript, поэтому я не думаю, что это может быть перехвачено.

Однако, что вы могли бы сделать, написать новую директиву, сохранить httpSrc. Затем он может получить изображение с помощью вызова $http, а затем создать URI данных с ответом, используя что-то вроде Использование необработанных данных изображения из запроса ajax для URI данных (хотя я не уверен в поддержке браузера).

Ответ 2

На основании ответа Михала директива может выглядеть следующим образом

app.directive('httpSrc', [
        '$http', function ($http) {
            var directive = {
                link: link,
                restrict: 'A'
            };
            return directive;

            function link(scope, element, attrs) {
                var requestConfig = {
                    method: 'Get',
                    url: attrs.httpSrc,
                    responseType: 'arraybuffer',
                    cache: 'true'
                };

                $http(requestConfig)
                    .then(function(response) {
                        var arr = new Uint8Array(response.data);

                        var raw = '';
                        var i, j, subArray, chunk = 5000;
                        for (i = 0, j = arr.length; i < j; i += chunk) {
                            subArray = arr.subarray(i, i + chunk);
                            raw += String.fromCharCode.apply(null, subArray);
                        }

                        var b64 = btoa(raw);

                        attrs.$set('src', "data:image/jpeg;base64," + b64);
                    });
            }

        }
    ]);

Затем вы будете использовать его следующим образом

<img http-src="www.test.com/something.jpeg">

Ответ 3

Как сказано здесь, вы можете использовать angular-img-http-src (bower install --save angular-img-http-srcесли вы используете Bower).

Если вы посмотрите код, он использует URL.createObjectURL и URL.revokeObjectURL, которые еще черновик 19 апреля 2016. Итак, посмотрите, поддерживает ли ваш браузер.

Чтобы использовать его, объявите 'angular.img' как зависимость от вашего модуля приложения (angular.module('myapp', [..., 'angular.img'])), а затем в своем HTML вы можете использовать атрибут http-src для тега <img>.

В вашем примере вы можете написать: <img http-src="/users/1/images/{{imageId}}">

Ответ 4

Это немного старо, но я подумал, что добавлю еще один метод поиска изображения без использования перехватчика. В моем случае мне нужно было найти путь изображения из конвейера ресурсов рельсов.

Был блог от Codetunes (http://codetunes.com/2014/5-tips-on-how-to-use-angularjs-with-rails-that-changed-how-we-work/), в котором описывалось, как они находят шаблоны. Это использует перехватчик, но не работает для изображений.

В используемом решении вам необходимо использовать модель для значения ng-src. В рамках модели я вызываю вспомогательный метод из службы, которая использует настройку переменной Rails.templates из указанной выше статьи блога.

Итак, это выглядит так:

angular.module('myApp').factory('RailsAssetService', function(Rails) {

    function RailsAssetService() {

    }

    RailsAssetService.getAssetsUrl = function(url) {
        var railsUrl = Rails.templates[url];
        if (railsUrl === undefined)
            railsUrl = url;
        return railsUrl;
    }

    return RailsAssetService;
});

и в контроллере:

vm.creditCardsImage = RailsAssetService.getAssetsUrl('credit-cards-logo.gif');

и в представлении:

<img ng-src="{{vm.creditCardsImage}}">