Подтвердить что ты не робот

$ http загружает файл прогресса в AngularJS

Как я могу получить событие "прогресс" из моего запроса на HTTP-запрос AngularJS $http, который загружает изображение? Возможно ли это сделать на стороне клиента или мне нужен сервер, чтобы сообщить о прогрессе, когда он получает данные?

4b9b3361

Ответ 1

Я не думаю, что для этого можно использовать $http.post().

Что касается клиентской стороны, он должен работать с браузером HTML5, но вам, вероятно, придется создать свой собственный объект XMLHttpRequest и onprogress прослушиватель. См. AngularJS: статус отслеживания каждого загружаемого файла одновременно для идей.

Ответ 2

Вы также можете использовать простую/легкую angular-file-upload директиву, которая позаботится об этом. Он поддерживает drag & падение, прогресс/прерывание файла и загрузку файлов для браузеров, отличных от HTML5, с помощью плагина FileAPI flash

<div ng-controller="MyCtrl">
  <input type="file" ng-file-select="onFileSelect($files)" multiple>
</div>

JS:

//inject angular file upload directive.
angular.module('myApp', ['angularFileUpload']);

var MyCtrl = [ '$scope', '$upload', function($scope, $upload) {
  $scope.onFileSelect = function($files) {
    //$files: an array of files selected, each file has name, size, and type.
    for (var i = 0; i < $files.length; i++) {
      var $file = $files[i];
      $upload.upload({
        url: 'my/upload/url',
        file: $file,
        progress: function(e){}
      }).then(function(data, status, headers, config) {
        // file is uploaded successfully
        console.log(data);
      }); 
    }
  }
}];

Ответ 3

Использование чистого angular:

function upload(data) {
    var formData = new FormData();
    Object.keys(data).forEach(function(key){formData.append(key, data[key]);});
    var defer = $q.defer();
    $http({
        method: 'POST',
        data: formData,
        url: <url>,
        headers: {'Content-Type': undefined},
        uploadEventHandlers: { progress: function(e) {
            defer.notify(e.loaded * 100 / e.total);
        }}
    }).then(defer.resolve.bind(defer), defer.reject.bind(defer));
    return defer.promise;
}

и где-то еще...

// file is a JS File object
upload({avatar:file}).then(function(responce){
    console.log('success :) ', response);
}, function(){
    console.log('failed :(');
}, function(progress){
    console.log('uploading: ' + Math.floor(progress) + '%');
});

Ответ 4

Я не думаю, что у Angular есть что-то встроенное для обработки загрузок.

Я думаю, что ваш лучший выбор - использовать что-то вроде jQuery File Upload. Идея для решения заключалась бы в создании Сервиса, который возвращает {progress:0} по умолчанию, а затем внутри себя, реализует обратный вызов обновления процесса загрузки файла jQuery, который затем просто продолжает обновлять прогресс. Благодаря привязке Angular процесс загрузки будет синхронизирован.

angular.module('myApp.services', [])
  .factory('Uploader', function() {
  var uploaderService = {};

  var status = { progress: 0 };

  uploaderService.upload = function(inputEl) {
    inputEl.fileupload({
      /* ... */
      progressall: function (e, data) {
        status.progress = parseInt(data.loaded / data.total * 100, 10);
      }
    });
  };

  return uploaderService;
});

Ответ 5

Вот еще одно решение:

window.XMLHttpRequest = (function (orig) {
    if (orig) {
        var intercept = [],
            result = function () {
            var r = new orig();

            if (r.upload) {
                $(r).on(
                    'abort error load loadend loadstart progress',
                    function (e) {
                        $(document).trigger('upload.XHR', e);
                    }
                );
            }

            if (intercept.length) {
                intercept[0].push({
                    request:r
                });
            }

            return r;
        };

        result.grab = function (f) {
            intercept.unshift([]);
            f();
            return intercept.shift();
        };

        return result;
    }

    return function () {
        try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {}
        try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {}
        try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {}
        throw new Error("This browser does not support XMLHttpRequest.");
    };
}(window.XMLHttpRequest));

Примечания:

  • В настоящее время функция AngularJS хранит ссылку на window.XMLHttpRequest как частную переменную XHR, а затем использует ее следующим образом: new XHR(). Я сомневаюсь, что это когда-нибудь изменится, поэтому вышеприведенный выше код должен работать нормально.

  • Mozilla имеет несколько расширений: XMLHttpRequest принимает необязательные аргументы. Код выше не справляется с этим, но AngularJS не использует эти расширения в любом случае.

  • Одно из возможных применений (если вы хотите показать все текущие запросы и, возможно, реализовать некоторую кнопку "Отмена" ):

$(document).on('upload.XHR', function (_e, e) {
   switch (e.type) {
       // do your thing here
   }
});
  • Еще одно возможное использование:
var list = window.XMLHttpRequest.grab(function () {
    // start one or more $http requests here, or put some code
    // here that indirectly (but synchronously) starts requests
    $http.get(...);
    couchDoc.save();
    couchDoc.attach(blob, 'filename.ext');
    // etc
});

list[0].request.upload.addEventListener(...);
  • Или вы можете комбинировать оба подхода с некоторыми изменениями в коде выше.

Ответ 6

вы можете использовать это, когда Im использует простую функцию angular для загрузки файла и переменной $scope.progressBar, чтобы проверить ход загрузки...

$scope.functionName = function(files) {
   var file = files[0];
   $scope.upload = $upload.upload({
   url: 'url',
   method: 'POST', 
   withCredentials: true, 
   data: {type:'uploadzip'},
   file: file, // or list of files ($files) for html5 only 
 }).progress(function(evt) {
   console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
   $scope.progressBar = parseInt(100.0 * evt.loaded / evt.total);
 }).success(function(data, status, headers, config) {
   console.log('upload succesfully...')
 }).error(function(err) {
   console.log(err.stack);
 }) 
}