Интеграция файлового загрузчика для angularjs

Существует ли хороший файл-загрузчик с хорошей интеграцией (директива) для AngularJS?

Я ищу что-то, что легко стильно и поддерживает перетаскивание HTML5 и т.д.

Кто-то, вероятно, скажет, что его простой в использовании существующий загрузчик и интеграция его в AngularJS - к тому, что я скажу: если его легко, то кто-то должен был это сделать уже.

Ответ 1

Я действительно закатил свой собственный загрузчик один раз... но только потому, что мне не нравились уже сделанные JQuery. К сожалению, это проприетарное, и я не могу опубликовать его в Интернете... но... Я могу показать вам, как использовать практически любой плагин JQuery из Angular:

Кто-то, вероятно, скажет, что его простой в использовании существующий загрузчик и интеграция его в AngularJS - к тому, что я скажу: если его легко, то кто-то должен был сделать это уже.

Предположим, что у меня есть плагин jQuery, который работает, выбирая div и вызывающий pluginUploadCall() на нем...

app.directive('myJqueryPluginUploader', function() {
   return {
      restrict: 'A',
      link: function(scope, elem, attr, ctrl) {
          // elem is a jQuery lite object
          // or a jQuery object if jQuery is present.
          // so call whatever plugins you have.
          elem.pluginUploadCall();
      }
   };
});

И вот как он будет использоваться.

<div my-jquery-plugin-uploader></div>

Angular действительно хорошо интегрируется с jQuery, поэтому любые плагины, которые работают в jQuery, должны работать довольно легко в Angular. Единственная хитрость возникает, когда вы хотите сохранить Injection Dependency вживую, чтобы вы могли поддерживать приложение Angular. JQuery не очень хорош в DI, поэтому вам, возможно, придется перепрыгнуть через некоторые обручи.

Если бы вы хотели перевернуть свои собственные, я могу сказать, что я сделал что-то вроде этого:

app.directive('customUploader', function(){
    return {
       restrict: 'E',
       scope: {},
       template: '<div class="custom-uploader-container">Drop Files Here<input type="file" class="custom-uploader-input"/><button ng-click="upload()" ng-disabled="notReady">Upload</button></div>',
       controller: function($scope, $customUploaderService) {
          $scope.notReady = true;
          $scope.upload = function() {
             //scope.files is set in the linking function below.
             $customUploaderService.beginUpload($scope.files);
          };
          $customUploaderService.onUploadProgress = function(progress) {
             //do something here.
          };
          $customUploaderService.onComplete = function(result) {
             // do something here.
          };
       },
       link: function(scope, elem, attr, ctrl) {
          fileInput = elem.find('input[type="file"]');
          fileInput.bind('change', function(e) {               
               scope.notReady = e.target.files.length > 0;
               scope.files = [];
               for(var i = 0; i < e.target.files.length; i++) {
                   //set files in the scope
                   var file = e.target.files[i];
                   scope.files.push({ name: file.name, type: file.type, size: file.size });
               }
          });
       }
});

Где $customUploaderService будет создаваться пользовательский сервис с Module.factory(), который использует $http для публикации файлов и проверки прогресса на сервере.

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

EDIT: Загрузка файла перетаскивания - это немного трюк CSS, BTW... для Chrome и FF, то, что вы делаете, помещается в содержащий div... затем сделайте что-то вроде этого:

<div class="uploadContainer">Drop Files Here<input type="file"/></div>
div.uploadContainer {
   position: relative;
   width: 600px;
   height: 100px;
}

div.uploadContainer input[type=file] {
   visibility: hidden;
   position: absolute;
   top: 0;
   bottom: 0;
   left: 0;
   right: 0;
}

... теперь все, что вы бросаете на этом div, действительно будет удалено при загрузке файла, и вы можете заставить div выглядеть так, как вам хочется.

Ответ 2

Вы можете попробовать AngularJS.ngUpload.

Это решение без HTML5, которое использует невидимый iFrame для загрузки файлов. Поскольку он не полагается на HTML5, он работает в браузере!

Пример кода:

<form action='/server/upload/handler' ng-upload="callbackFunction">
   <!-- other form inputs goes here -->
   <input type="file" name="anyEasyName" />
   <input type="submit" class="upload-submit" value="Submit" />
</form>
<div>{{uploadReport}}</div>

Любой элемент html, который поддерживает событие click, может быть использован для отправки формы, помеченной директивой ngUpload, только чтобы такие элементы были отмечены классом upload-submit css (в случае с вход [type = submit] выше.

В приведенном ниже примере используется стилизованный div для отправки формы.

<form action='/server/upload/handler' ng-upload="callbackFunction">
   <!-- other form inputs goes here -->
   <input type="file" name="anyEasyName" />
   <div style="cursor: pointer; padding: 5px" class="upload-submit">Submit</div>
</form>
<div>{{uploadReport}}</div>

Вы можете заставить ваш/сервер/загрузку/обработчик спрятать действительный URL-адрес, чтобы {{uploadReport}} мог использоваться для установки src в <img> тег, например:

<img ng-src={{uploadReport}} />

и сразу увидите загруженное изображение!

ngController для приведенных выше примеров:

var UploadCtrl = function ($scope) {
     $scope.callbackFunction = function(contentOfInvisibleFrame) {
         $scope.uploadReport = contentOfInvisibleFrame;
     }
}

Директива ngUpload может быть зарегистрирована в вашем прикладном модуле AngularJS, а именно:

var mainApp = angular.module('MainApp', ["ngUpload", ...]);

и добавлен в ваш документ как:

<html ng-app="MainApp">

</html>

AngularJS.ngUpload работает в контексте ngController; и у вас может быть как можно больше пользователей в одном ngController. Например:

<form action='/server/upload/handler' ng-upload="callbackFunction1">
   <!-- other form inputs goes here -->
   <input type="file" name="anyEasyName" />
   <input type="submit" class="upload-submit" value="Submit" />
</form>
Server response: {{uploadReport1}}

<form action='/server/upload/handler' ng-upload="callbackFunction2">
   <!-- other form inputs goes here -->
   <input type="file" name="anotherEasyName" />
   <input type="submit" class="upload-submit" value="Submit" />
</form>
Server response: {{uploadReport2}}

для обслуживания:

var UploadCtrl = function ($scope) {
     $scope.callbackFunction1 = function(contentOfInvisibleFrame) {
         $scope.uploadReport1 = contentOfInvisibleFrame;
     }

     $scope.callbackFunction2 = function(contentOfInvisibleFrame) {
         $scope.uploadReport2 = contentOfInvisibleFrame;
     }
}

Демоверсию обработчика загрузки NodeJS этой директивы можно найти на http://ng-upload.eu01.aws.af.cm.

Примеры кода ASP.Net MVC и NodeJS можно найти на веб-сайте проекта по адресу github.com/twilson63/ngUpload/tree/master/examples

Надеюсь, что это поможет.

Ответ 3

Я собрал простую/легкую директиву angular с polyfill для браузеров, не поддерживающих HTML5 FormData здесь:

https://github.com/danialfarid/ng-file-upload

Вы можете отправить другой объект модели вместе с файлом на сервер. Вот демонстрационная страница:

http://angular-file-upload.appspot.com/

<script src="angular.min.js"></script>
<script src="ng-file-upload.js"></script>

<div ng-controller="MyCtrl">
  <input type="text" ng-model="myModelObj">
  <input type="file" ngf-select ng-model="files" >
</div>

контроллер:

Upload.upload({
    url: 'my/upload/url',
    data: {myObj: $scope.myModelObj},
    file: $scope.files
  }).then(function(data, status, headers, config) {
    // file is uploaded successfully
    console.log(data);
  }); 

Ответ 4

Если вы хотите обрабатывать несколько файлов, попробуйте это

jQuery Загрузка файла Angularjs wrap от оригинального автора (blueimp)

Я думаю, что это самый мощный загрузчик.

Ответ 5

Недавно я написал директиву, поддерживающую несколько загрузок файлов.

Пример использования:

<lvl-file-upload
    auto-upload='false'
    choose-file-button-text='Choose files'
    upload-file-button-text='Upload files'
    upload-url='http://localhost:3000/files'
    max-files='10'
    max-file-size-mb='5'
    get-additional-data='getData(files)'
    on-done='done(files, data)'
    on-progress='progress(percentDone)'
    on-error='error(files, type, msg)'/>

Вы можете найти код на github, а документацию на my блог